Client/server Bad value on output port 'tcp_inet'
Lars H. Larsen, ICCC
LHL@REDACTED
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:lhl@REDACTED
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('LMDPLU@REDACTED').
-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