2 * Amiga Generic Set - set of libraries and includes to ease sw development for all Amiga platforms
3 * Copyright (C) 2001-2011 Tomasz Wiszkowski Tomasz.Wiszkowski at gmail.com.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "LibrarySpool.h"
21 #include "NetSocket.h"
22 #include "Synchronizer.h"
23 #include <libclass/bsdsocket.h>
24 #include <libdata/bsdsocket/netdb.h>
25 #include <libdata/bsdsocket/in.h>
26 #include <libdata/bsdsocket/ioctl.h>
27 #include <libdata/bsdsocket/socketbasetags.h>
28 #include <libclass/exec.h>
29 #include "LibrarySpool.h"
30 #include <LibC/LibC.h>
31 #include <libclass/dos.h>
33 using namespace GenNS
;
41 int32
NetSocket::stTrue
= 1;
42 int32
NetSocket::stFalse
= 0;
44 NetSocket::NetSocket(NetSocket::SocketID
*socket
, bool isserv
)
46 FConstruct(socket
, isserv
);
49 void NetSocket::FConstruct(NetSocket::SocketID
*socket
, bool server
)
53 addr_local
= new sockaddr_in
;
54 addr_remote
= new sockaddr_in
;
56 bsock
= BSDSocketIFace::GetInstance(0);
67 temp
= Exec
->AllocSignal(-1);
71 lSocket
= (socket
) ? bsock
->ObtainSocket(socket
->id
, socket
->domain
, socket
->type
, socket
->proto
) : -1;
72 bConnected
= (lSocket
>= 0) ? true : false;
80 NetSocket::~NetSocket()
84 bsock
->FreeInstance();
89 bool NetSocket::FResolve(char* AHost
, int APort
, sockaddr_in
*AAddr
)
93 hostent
*pHost
= bsock
->gethostbyname(AHost
);
97 Exec
->CopyMem(pHost
->h_addr_list
[0], &AAddr
->sin_addr
, sizeof(AAddr
->sin_addr
));
101 AAddr
->sin_addr
.s_addr
= bsock
->inet_addr(AHost
);
102 if (AAddr
->sin_addr
.s_addr
== 0xffffffff)
108 AAddr
->sin_addr
.s_addr
= INADDR_ANY
;
111 AAddr
->sin_family
= AF_INET
;
112 AAddr
->sin_port
= W2BE(APort
);
116 bool NetSocket::FSetupSocket()
118 uint32 lSockEvMask
= FD_CONNECT
| FD_READ
| FD_WRITE
| FD_CLOSE
| FD_ERROR
;
124 bsock
->setsockopt(lSocket
, SOL_SOCKET
, SO_EVENTMASK
, &lSockEvMask
, sizeof(unsigned long));
127 //request("", "Unable to set socket options", "Ok", 0);
132 error
= bsock
->setsockopt(lSocket
, SOL_SOCKET
, SO_KEEPALIVE
, &stTrue
, sizeof(stTrue
));
135 //request("", "Unable to set socket options", "Ok", 0);
140 error
= bsock
->setsockopt(lSocket
, SOL_SOCKET
, SO_SNDBUF
, &bs
, sizeof(bs
));
143 //request("", "Unable to set socket options", "Ok", 0);
148 error
= bsock
->setsockopt(lSocket
, SOL_SOCKET
, SO_RCVBUF
, &bs
, sizeof(bs
));
151 //request("", "Unable to set socket options", "Ok", 0);
155 bsock
->IoctlSocket(lSocket
, FIONBIO
, (char*)&stFalse
);
156 // bsock->IoctlSocket(lSocket, FIOASYNC, (char*)&stTrue);
161 bool NetSocket::FConnect(char* AHost
, int16 APort
, SocketType stype
)
168 lSocket
= bsock
->socket(AF_INET
, FTypeToInet(stype
), 0);
173 if (!FResolve(AHost
, APort
, &addr
))
175 request("", "Unable to resolve host name", "Ok", 0);
180 error
= bsock
->connect(lSocket
, (sockaddr
*)&addr
, sizeof(addr
));
183 request("", "Unable to connect", "Ok", 0);
196 void NetSocket::FGetAddresses()
205 i
= sizeof(addr_local
);
206 bsock
->getsocketname(lSocket
, (sockaddr
*)addr_local
, &i
);
207 i
= sizeof(addr_local
);
208 bsock
->getpeername(lSocket
, (sockaddr
*)addr_remote
, &i
);
212 void NetSocket::FDisconnect()
217 bsock
->shutdown(lSocket
, 2);
218 bsock
->CloseSocket(lSocket
);
226 bool NetSocket::FBind(int16 APort
, SocketType stype
)
229 uint32 lSockEvMask
= FD_CONNECT
| FD_ACCEPT
| FD_READ
| FD_CLOSE
| FD_ERROR
;
234 lSocket
= bsock
->socket(AF_INET
, FTypeToInet(stype
), 0);
235 bsock
->setsockopt(lSocket
, SOL_SOCKET
, SO_EVENTMASK
, &lSockEvMask
, sizeof(unsigned long));
236 bsock
->setsockopt(lSocket
, SOL_SOCKET
, SO_KEEPALIVE
, &stTrue
, sizeof(stTrue
));
237 bsock
->IoctlSocket(lSocket
, FIONBIO
, (char*)&pTrue
);
238 bsock
->IoctlSocket(lSocket
, FIOASYNC
, (char*)&pTrue
);
240 if (!FResolve(0, APort
, &addr
))
246 error
= bsock
->bind(lSocket
, (sockaddr
*)&addr
, sizeof(addr
));
253 error
= bsock
->listen(lSocket
, 5);
266 int32
NetSocket::FTypeToInet(SocketType stype
)
281 bool NetSocket::FTryAccept(NetSocket::SocketID
*s
)
284 int32 laddr
= sizeof(sockaddr
);
286 /* FIXME: very very very basic stuff. need to allow other types too? not sure - dgram is connectionless.
288 s
->id
= bsock
->ReleaseSocket(bsock
->accept(lSocket
, &saddr
, &laddr
), 65536 + Utility
->GetUniqueID());
290 s
->type
= SOCK_STREAM
;
293 return (s
->id
!= -1);
296 int32
NetSocket::ReadBuffer(void* buffer
, int32 maxlen
)
298 return FReadBuffer(buffer
, maxlen
);
301 int32
NetSocket::WriteBuffer(void* buffer
, int32 maxlen
)
303 return FWriteBuffer(buffer
, maxlen
);
306 int32
NetSocket::FReadBuffer(void* buff
, int32 len
)
316 bytes = WaitStatus(~0, 0);
317 if (bytes & SEv_Disconnected)
319 } while (0 == (bytes & SEv_DataReady));
322 //bsock->IoctlSocket(lSocket, FIONREAD, &bytes);
327 bytes
= bsock
->recv(lSocket
, buff
, len
, MSG_WAITALL
);
329 if (Errno() != 11) // EAGAIN
342 int32
NetSocket::Errno()
344 return bsock
->Errno();
347 int32
NetSocket::FWriteBuffer(void* buff
, int32 len
)
356 bs
= WaitStatus(~0, 0, SEv_WriteReady
| SEv_Disconnected
);
357 if (bs
& SEv_Disconnected
)
359 } while (0 == (bs
& SEv_WriteReady
));
365 bs
= bsock
->send(lSocket
, &((char*)buff
)[sent
], len
< 32768 ? len
: 32768, 0);
367 if (Errno() != 11) // EAGAIN
373 len
-= bs
, sent
+= bs
;
379 bool NetSocket::Listen(int APort
, SocketType stype
)
381 return FBind(APort
, stype
);
384 bool NetSocket::Connect(char* AHost
, int APort
, SocketType stype
)
386 return FConnect(AHost
, APort
, stype
);
389 void NetSocket::Disconnect()
394 bool NetSocket::Accept(NetSocket::SocketID
* sid
)
396 return FTryAccept(sid
);
399 void NetSocket::SetSignals(uint32 signal
)
403 Exec
->FreeSignal(nSignal
);
407 bsock
->SocketBaseTagList((TagItem
*)ARRAY(SBTC_SIGEVENTMASK
, lSignal
, 0));
408 bsock
->SetSocketSignals(0, lSignal
, 0);
411 uint32
NetSocket::GetSignals()
416 int32
NetSocket::GetDataAvail()
420 error
= bsock
->IoctlSocket(lSocket
, FIONREAD
, &bytes
);
423 request("Info", "Disconnected? (get data avail)", "Ok", 0);
428 uint32
NetSocket::FGetStatus(uint32 millis
, uint32 sigs
, uint16 events
)
435 (millis
% 1000) * 1000
439 return SEv_Disconnected
; // unmaskable...
441 memset(&rx
, 0, sizeof(rx
));
442 memset(&wx
, 0, sizeof(rx
));
443 if (events
& (SEv_DataReady
| SEv_IncomingCall
))
444 FD_SET(lSocket
, &rx
);
445 if (events
& (SEv_WriteReady
))
446 FD_SET(lSocket
, &wx
);
448 Exec
->CopyMem(&rx
, &ex
, sizeof(rx
));
450 if ((sock
= bsock
->WaitSelect(lSocket
+ 1, &rx
, &wx
, &ex
, &tv
, &sigs
)) < 0)
452 return SEv_Disconnected
;
455 //request("Info", "%ld %lx %lx %lx", "Ok", ARRAY(sock, rx.fds_bits[0], wx.fds_bits[0], ex.fds_bits[0]));
459 sock
|= SEv_OtherEvent
;
461 if (FD_ISSET(lSocket
, &rx
))
465 sock
|= SEv_DataReady
;
468 sock
|= SEv_IncomingCall
;
471 if (FD_ISSET(lSocket
, &wx
))
472 sock
|= SEv_WriteReady
;
474 Exec
->SetSignal(sigs
, sigs
);
479 uint32
NetSocket::GetStatus()
481 return FGetStatus(0, 0, SEv_AllEvents
);
484 uint32
NetSocket::WaitStatus(uint32 millis
, uint32 sigs
, uint16 events
)
486 return FGetStatus(millis
, sigs
, events
);
489 uint32
NetSocket::GetLocalIP()
493 return addr_local
->sin_addr
.s_addr
;
496 uint16
NetSocket::GetLocalPort()
500 return addr_local
->sin_port
;
503 uint32
NetSocket::GetRemoteIP()
507 return addr_remote
->sin_addr
.s_addr
;
510 uint16
NetSocket::GetRemotePort()
514 return addr_remote
->sin_port
;