Client/server Bad value on output port 'tcp_inet'

Lars H. Larsen, ICCC <>
Tue Feb 4 11:40:49 CET 2003


Hello fabulous Erlang guys 

I'm using OTP R9-0 on a Win32 platform (winsock) W2K and XP

When I run a balanced client-server program ( attached below) the connection phase is resolved with no problems.
But the data exchange never happens due to some strange error I have been chasing now for a week or so, 
-until now with no luck.... :-(

in Desperation I loaded the program with debug outputs :  All the debug output  give approx. this result on both sides when connecting from  'knud2' to 'lhl-pc'

accsocket init <0.72.0>,knud2 6000 
accsocket: gen_tcp:connect(knud2,6000),{packet, 0},{active, true }
Connect error {reason,econnrefused} 
gen_tcp:listen (6000,[binary, {packet, 0}, {active,true}])
ok,ListenSocket  ListenSocket=#Port<0.118> info ={error,enotconn}
runing initServer got Connect Socket #Port<0.119> Info {ok,{{192,168,2,253},
                                                            6000}}
GETACCTABLE Socket#socket.socket #Port<0.119> Data {[255,0,0,2]}
accsocket:send(#Port<0.119>,{[255,0,0,2]})
accsock:error Reasson einval

=ERROR REPORT==== 4-Feb-2003::11:23:55 ===
Bad value on output port 'tcp_inet'

- the ERROR thing  text is repeated for every data send attempt


regards
Software developer
Lars H. Larsen
ICCC A/S
Måløvhovedgade 88
2760 Måløv
Denmark
http://www.iccc.dk
mailto:
tel:+45 44860400
GSM +45 51901320


here is a printout of the program accsocket.erl,  the real fun happens in function socketLoop/1

========================================================== cut here

-define(module, accsocket).                         % The name of this module.
-module(?module).
-compile({module_info, [{identity, '@(#)AccSocket/R4A01'}]}).

-author('').

-export([socketLoop/1, init/3, initServer/3]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Constants.
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Definition of the alarm numbers used in the alarmlist.def file
-define(alarmbase,                              1500         ).
-define(unknownMessageReceived,                 ?alarmbase+1 ).
-define(accGwWentDown,                          ?alarmbase+31).
-define(socketTransmissionError,                ?alarmbase+32).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Records.
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-define(loopRecordName, socket).% To be used in the record definition and in
                                % the debug.hrl file.

-record( ?loopRecordName,
       { socket = unknown,      % The Socket reference.
         gwPid,                 % The Pid of the 'ACCGW' process.
         ipAddress,             % The ip address of the socket process.
         socketPort,            % The socket port used to communicate ...
         restData = [],         % The Pid of the 'ACCGW' process.
         hostType,              % The type of the socket connection [server|client].
         logSocketCommand = #log{eventLevel=210, eventString="ACCSOCKET: Command decoded: "},
         logSocketData    = #log{eventLevel=210, eventString="ACCSOCKET: SocketData received: "},
         logAlarm         = #log{eventLevel=255, eventString="ACCSOCKET Alarm: "}
       }).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Debug functions and records.
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-define(regName, 'ACCSOCKET').      % The registerred name.
-include("debug.hrl").


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Function	: init/3
%% Purpose	: initiates the socket from the gateway. 
%% Args		: Port	- Variable containing the port number the gateway will use for sockets
%% Return	: Spawns 2 processes, a client and a server.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init(GwPid, IpAddress, Port) when pid(GwPid), atom(IpAddress), integer(Port)->
    io:fwrite("accsocket init ~p,~p ~p ~n",[GwPid, IpAddress, Port]),
	process_flag(trap_exit, true),
    register(?regName, self()),
	%LHL socket:start(),
	initClientLoop(#socket{gwPid=GwPid, ipAddress=IpAddress, socketPort=Port, hostType=client});

init(_, _, _) ->
	io:fwrite("Bad parameter").


initClientLoop(SocketRec)->
	timer:sleep(100), % Please don't ask why !
	
	io:format("accsocket: gen_tcp:connect(~w,~w),{packet, 0},{active, true }~n",[SocketRec#socket.ipAddress, SocketRec#socket.socketPort]),
	case catch gen_tcp:connect(SocketRec#socket.ipAddress, SocketRec#socket.socketPort, [binary,{packet,0},{active,true}]) of
		{error, _R} ->
			io:format("Connect error {reason,~w} ~n",[_R]),
        	ServerPid = spawn_link(?module, initServer, [self(), SocketRec#socket.ipAddress, SocketRec#socket.socketPort]),
			initServerLoop(SocketRec#socket{hostType=server}, ServerPid);
		
		{'EXIT', _Reason} ->
			io:format("Connect EXIT {reason,~w} ~n",[_Reason]),
        	ServerPid = spawn_link(?module, initServer, [self(), SocketRec#socket.ipAddress, SocketRec#socket.socketPort]),
			initServerLoop(SocketRec#socket{hostType=server}, ServerPid);
		{ok,Socket}  -> 
			io:format("runing initclient got Connect ~p ~n",[Socket]),
			SocketRec#socket.gwPid ! {'SOCKETSTATE',active},
			socketLoop(SocketRec#socket{socket = Socket})
		
	end.

initServerLoop(SocketRec, ServerPid)->
	receive

		{'EXIT', ServerPid, Reason} ->
			io:format("{'EXIT', ServerPid, Reason}: ~p ~n",[Reason]),
			initClientLoop(SocketRec#socket{hostType=client});

		{'EXIT', GwPid, Reason} ->
			alarmmgr:notify(?accGwWentDown, [?MODULE, ?LINE, Reason]),
			log(SocketRec, logAlarm, {notify, ?accGwWentDown, ?MODULE, ?LINE, [Reason]}),
			exit(Reason);

		{'ACCSOCKETCONNECT', ServerPid, Socket} ->
			SocketRec#socket.gwPid ! {'SOCKETSTATE', active},
			socketLoop(SocketRec#socket{socket = Socket});

    	{'UPDATECODE', Module} ->
			unlink(ServerPid),
			exit(ServerPid, kill),
			case Module of
			?module ->
				?module:initClientLoop(SocketRec#socket{hostType=client});
			_Module ->
				initClientLoop(SocketRec#socket{hostType=client})
			end;

		{'SHUTDOWN', Pid} ->
			unlink(ServerPid),
			exit(ServerPid, kill),
%			io:fwrite('  SHUTDOWN request sent from ACCGW  '),
			Pid ! {'SHUTDOWNOK',self()},
			initClientLoop(SocketRec#socket{hostType=client});

    %------------------------ Debug Functionallity --------------------------%

        {getLoopData, Pid} ->
            Pid ! {loopData, SocketRec},
            initServerLoop(SocketRec, ServerPid);

        {logState, LogRecord, NewValue} ->
            NewSocketRec = logStateChange(SocketRec, LogRecord, NewValue),
            initServerLoop(NewSocketRec, ServerPid);

        {logToScreen, LogRecord, NewValue} ->
            NewSocketRec = logToScreenChange(SocketRec, LogRecord, NewValue),
            initServerLoop(NewSocketRec, ServerPid);

        {logLevel, LogRecord, NewValue} ->
            NewSocketRec = logLevelChange(SocketRec, LogRecord, NewValue),
            initServerLoop(NewSocketRec, ServerPid);

        exit ->
            ok;

        Other ->
        	io:format("SocketLoop Other: ~p ~n",[Other]),
            alarmmgr:notify(?unknownMessageReceived, [?MODULE, ?LINE, Other]),
            log(SocketRec, logAlarm, {notify, ?unknownMessageReceived, ?MODULE, ?LINE, [Other]}),
            initServerLoop(SocketRec, ServerPid)

% 		after TimeOut ->
% 			unlink(ServerPid),
%			exit(ServerPid, kill),
%			initClientLoop(SocketRec#socket{hostType=client})

	end.

initServer(Initiator, IpAddress, Port)->
	%LHL ListenSocket = socket:listen('STREAM', 'AF_INET', Port, {packet, 0}), 

	io:format("gen_tcp:listen (~w,[binary, {packet, 0}, {active,true}])~n",[Port]),
	
	case catch gen_tcp:listen(Port,[binary, {packet, 0}, {active,true}]) of
		{error,Reason} -> 
			io:format("Exit in listen (~w) ~n",[Reason]),
			exit(normal);		
		
		{ok,ListenSocket} ->
		    io:format("ok,ListenSocket  ListenSocket=~p info =~p~n",[ListenSocket,inet:peername(ListenSocket)]),
			case catch gen_tcp:accept(ListenSocket) of  
			{error, Reason} ->
				io:format("Error gen_tcp:accept Reason~p ~n",[Reason]),
				%gen_tcp:close(ListenSocket),
				exit(normal);		
	
			{ok,Socket}->
			    io:format("runing initServer got Connect Socket ~p Info ~p~n",[Socket,inet:sockname(Socket)]),
				Initiator ! {'ACCSOCKETCONNECT', self(), Socket},
				%LHL socket:controlling_process(Socket, Initiator),
				gen_tcp:controlling_process(Socket, Initiator),
				unlink(Initiator),
				gen_tcp:close(ListenSocket),
				ok
			end
	end.




	


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Function	: socketLoop/4
%% Purpose	: Loop that sends and receive data. 
%% Args		: Socket - loop data
%% Return	: --
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

socketLoop(Socket) ->    
	receive
	{tcp,SocketPid, SocketData} when SocketPid == Socket#socket.socket ->
		log(Socket, logSocketData, SocketData),
		
		io:format("Data from socket ~p~n",[SocketData]),
	   	case accDecode(lists:flatten([Socket#socket.restData|SocketData])) of
			{reply, Data} -> 
				log(Socket, logSocketCommand, {'NEWACCTABLE', Data}),
				Socket#socket.gwPid ! {'NEWACCTABLE', Data},
				socketLoop(Socket#socket{restData=[]});
		 		
		    {request} ->
				log(Socket, logSocketCommand, {'GETACCTABLE'}),
				Socket#socket.gwPid ! {'GETACCTABLE'},
				socketLoop(Socket#socket{restData=[]});

		    {splitData, {reply, Data}, RestData} ->
				log(Socket, logSocketCommand, [{'NEWACCTABLE', Data}, RestData]),
				Socket#socket.gwPid ! {'NEWACCTABLE', Data},
				socketLoop(Socket#socket{restData=RestData});

		    {splitData, {request}, RestData} ->
				log(Socket, logSocketCommand, [{'GETACCTABLE'}, RestData]),
				Socket#socket.gwPid ! {'GETACCTABLE'},
				socketLoop(Socket#socket{restData=RestData});

		    {packetNotEnded, RestData} ->
				socketLoop(Socket#socket{restData=RestData});

		    {error, invalidPacket} ->
				alarmmgr:notify(?socketTransmissionError, [?MODULE, ?LINE, [Socket#socket.restData|SocketData]]),
		        log(Socket, logAlarm, {notify, ?socketTransmissionError, ?MODULE, ?LINE, [Socket#socket.restData|SocketData]}),
				socketLoop(Socket#socket{restData=[]})

		end;

    {tcp_closed,SocketPid} when SocketPid == Socket#socket.socket ->
    	io:format("socket_closed,normal~n"),
        exit(normal);

    {tcp_error,SocketPid,Error} when SocketPid == Socket#socket.socket ->
    	io:format("socket_closed,Error ~p~n",[Error]),
        exit(Error);

	{'GETACCTABLE'} ->
		Data= {[255, 0, 0, 2]},
		io:format("GETACCTABLE Socket#socket.socket ~p Data ~p~n",[Socket#socket.socket,Data]),
		send(Socket#socket.socket,Data),
			% LHL Socket#socket.socket ! {self(),{deliver,[255, 0, 0, 2]}},
		socketLoop(Socket);


	{'NEWACCTABLE', Data} ->
		Data1 = accEncode(Data),
		io:format("NEWACCTABLE Socket#socket.socket ~p Data1 ~p~n",[Socket#socket.socket,Data1]),
		send(Socket#socket.socket,Data1),
		socketLoop(Socket);

    {'EXIT', Pid, Reason} when Pid == Socket#socket.gwPid ->
        alarmmgr:notify(?accGwWentDown, [?MODULE, ?LINE, Reason]),
        log(Socket, logAlarm, {notify, ?accGwWentDown, ?MODULE, ?LINE, [Reason]}),
        exit(Reason);

    {'UPDATECODE', ?module} ->
    	    ?module:socketLoop(Socket);

    {'UPDATECODE', Module} ->
			socketLoop(Socket);

	{'SHUTDOWN', Pid} ->
%		io:fwrite('  SHUTDOWN request sent from ACCGW  '),
		Pid ! {'SHUTDOWNOK',self()},
		socketLoop(Socket);

    %------------------------ Debug Functionallity --------------------------%

    {getLoopData, Pid} ->
        Pid ! {loopData, Socket},
        socketLoop(Socket);

    {logState, LogRecord, NewValue} ->
        NewSocket = logStateChange(Socket, LogRecord, NewValue),
        socketLoop(NewSocket);

    {logToScreen, LogRecord, NewValue} ->
        NewSocket = logToScreenChange(Socket, LogRecord, NewValue),
        socketLoop(NewSocket);

    {logLevel, LogRecord, NewValue} ->
        NewSocket = logLevelChange(Socket, LogRecord, NewValue),
        socketLoop(NewSocket);

    exit ->
        ok;

    Other ->
        alarmmgr:notify(?unknownMessageReceived, [?MODULE, ?LINE, Other]),
        log(Socket, logAlarm, {notify, ?unknownMessageReceived, ?MODULE, ?LINE, [Other]}),
        socketLoop(Socket)

end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Function	: accDecode/1
%%% 
%%% Purpose	: Checks and deocode the received packets from the other call centre, and 
%%%		  sends them to Alternative Call Centre Gateway (ACCGW). 
%%%
%%% Args	: [255, Length1, Length2, Command | DataList] - The list, which is received to be decoded.
%%%		 						255 is a flag indicating start of the packet. 
%%%		  						Lenght1 and Lenght2 are representing the total
%%%								lenght of the packet. 
%%%								Command is type os the packet, which either is
%%%								1 indicating "reply" or 2 indicating "request". 
%%%								DataList is a list of tuples of Service Type and
%%%								the expected queuing time.
%%% Return	: error - The received packet is not valid.
%%%		  {reply, decodeElements(DataList)} - "reply" is the type of the packet,and the value of
%%%						       decodeElements(DataList) is decoded received data. 
%%%
%%%		  {request} - "request" is the type of the packet.
%%%
%%%		  {packetNotEnded, DataList} - "packetNotEnded" indicates that the received packet is too short.
%%%
%%%		  {splitData, accDecode(NewDataList), RestData} - "splitData" indicates the received packet had

%%%								  been too long, and is splitet into "NewDataList"
%%%							 	  and "RestData".	
%%%		  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
accDecode([255,0,0,2]) ->
	{request};

accDecode([255, Length1, Length2, 1 | DataList]) ->
	Length = (Length1 * 256) + Length2,
	case decodeList(Length, DataList) of
		packetOK ->
			{reply, decodeElements(DataList)};
		packetNotEnded ->
			{packetNotEnded, DataList};
		{packetTooLong, {NewDataList, RestData}} ->
			{splitData, accDecode(NewDataList), RestData}	    
	end;

accDecode(_) ->
	{error, invalidPacket}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Function	: splitList/2
%%% 
%%% Purpose	: Split a list into two at a specified length.  
%%%
%%% Args	: List - The list, which is to be splitet into two. 
%%%		  Splitpoint - The number of enteries before splitting.
%%%
%%% Return	: {FirstList, SecondList} - FirstList is the list before the 
%%%					    split point. SecondList is the 
%%%					    remainder of the list after the split point.	
%%%		  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
splitList(List, SplitPoint) ->
	splitList(List, SplitPoint, []).

splitList([H | RestOfList], N, FirstList) when N > 0 ->
	splitList(RestOfList, N - 1, [H | FirstList]);

splitList(SecondList, 0, FirstList) ->
	{lists:reverse(FirstList), SecondList}.	

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Function	: decodeList/2
%%% 
%%% Purpose	: Checks the lenght of the data and call the split fucntion, if the 
%%%		  data is too long.
%%%
%%% Args	: Length - The total length of the data.
%%%
%%% Return	: packetNotEnded - Indicates that the received packet is too short.
%%%		  {packetTooLong, splitList(DList, Length)} - "packetTooLong" indicates
%%%							      the list/data is too long,
%%%							      and has to be splitet.	
%%%		  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decodeList(Length, DList) ->
	ListLength = length(DList),
	case Length of
	ListLength ->
		packetOK;		
	N when N > ListLength ->
		packetNotEnded;
	_ ->
		{packetTooLong, splitList(DList, Length)}		
	end.
							
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Function	: decodeElement/1
%%% 
%%% Purpose	: Decode the list into a list of tuples of two elements.
%%%
%%% Args	: List - A flatten list.
%%%
%%% Return	: Data - A list of tuples of Service Type and expected queuing time..	
%%%		  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decodeElements([]) ->
	[];

decodeElements([ServT1, ServT2, QT1, QT2 | Tail]) ->
	decodeElements([ServT1, ServT2, QT1, QT2 | Tail], []).


decodeElements([ServT1, ServT2, QT1, QT2 | Tail], Data) ->
	NewData = [{ServT1 * 256 + ServT2, QT1 *256 + QT2} | Data],
	decodeElements(Tail, NewData);
		
decodeElements([], Data) ->
	Data.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Function: accEncode/1 & /2
%%% 
%%% Purpose	: Encode the received OCC tuple to be a list of bytes including
%%%			  a start flag (255) length of data and 1 for request. 
%%%
%%% Args	: Data - A list of tuples to be encoded.
%%%				
%%% Return	: [255, 0, 0, 1] or [255, Length1, Length2, 1 | EncodedData)]
%%%		  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
accEncode(Data) ->
	accEncode(Data, []).

accEncode([], []) ->
	[255, 0, 0, 1];

accEncode([], EncodedData) ->
	Length = length(EncodedData),
	Length1 = Length div 256,
	Length2 = Length rem 256,
	[255, Length1, Length2, 1 | EncodedData];

accEncode([{ServiceType, QueueTime}|RestData], EncodedData) ->
	accEncode(RestData, [ServiceType div 256, ServiceType rem 256, QueueTime div 256, QueueTime rem 256 | EncodedData]).


send(Socket, Data)->
	io:format("accsocket:send(~p,~p)~n",[Socket,Data]),
	erlang:ports(),
	case gen_tcp:send(Socket, Data) of
%	 Socket ! {self(), Data}.
		ok ->
			io:format("accsock:send-> ok~n"),
			ok;

		{error, Reason} ->
	s			io:format("accsock:error Reasson ~p~n",[Reason]),
			erlang:ports(),
			exit(Reason)
	end.







More information about the erlang-questions mailing list