bbsockets.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. #include "std.h"
  2. #include "bbsockets.h"
  3. static bool socks_ok;
  4. static WSADATA wsadata;
  5. static int recv_timeout;
  6. static int read_timeout;
  7. static int accept_timeout;
  8. static void close( SOCKET sock,int e ){
  9. if( e<0 ){
  10. int opt=1;
  11. setsockopt( sock,SOL_SOCKET,SO_DONTLINGER,(char*)&opt,sizeof(opt) );
  12. }
  13. closesocket( sock );
  14. }
  15. class UDPStream;
  16. class TCPStream;
  17. class TCPServer;
  18. static set<UDPStream*> udp_set;
  19. static set<TCPStream*> tcp_set;
  20. static set<TCPServer*> server_set;
  21. class UDPStream : public bbStream{
  22. public:
  23. UDPStream( SOCKET s );
  24. ~UDPStream();
  25. int read( char *buff,int size );
  26. int write( const char *buff,int size );
  27. int avail();
  28. int eof();
  29. int recv();
  30. int send( int ip,int port );
  31. int getIP();
  32. int getPort();
  33. int getMsgIP();
  34. int getMsgPort();
  35. private:
  36. SOCKET sock;
  37. vector<char> in_buf,out_buf;
  38. sockaddr_in addr,in_addr,out_addr;
  39. int in_get,e;
  40. };
  41. UDPStream::UDPStream( SOCKET s ):sock(s),in_get(0),e(0){
  42. int len=sizeof(addr);
  43. getsockname( s,(sockaddr*)&addr,&len );
  44. in_addr=out_addr=addr;
  45. }
  46. UDPStream::~UDPStream(){
  47. close( sock,e );
  48. }
  49. int UDPStream::read( char *buff,int size ){
  50. if( e ) return 0;
  51. int n=in_buf.size()-in_get;
  52. if( n<size ) size=n;
  53. memcpy( buff,&in_buf[in_get],size );
  54. in_get+=size;
  55. return size;
  56. }
  57. int UDPStream::write( const char *buff,int size ){
  58. if( e ) return 0;
  59. out_buf.insert( out_buf.end(),buff,buff+size );
  60. return size;
  61. }
  62. int UDPStream::avail(){
  63. if( e ) return 0;
  64. return in_buf.size()-in_get;
  65. }
  66. int UDPStream::eof(){
  67. return e ? e : in_get==in_buf.size();
  68. }
  69. //fill buffer, return sender
  70. int UDPStream::recv(){
  71. if( e ) return 0;
  72. int tout;
  73. if( recv_timeout ) tout=gx_runtime->getMilliSecs()+recv_timeout;
  74. for(;;){
  75. int dt=0;
  76. if( recv_timeout ){
  77. dt=tout-gx_runtime->getMilliSecs();
  78. if( dt<0 ) dt=0;
  79. }
  80. fd_set fd={ 1,sock };
  81. timeval tv={ dt/1000,(dt%1000)*1000 };
  82. int n=::select( 0,&fd,0,0,&tv );
  83. if( !n ) return 0;
  84. if( n!=1 ){ e=-1;return 0; }
  85. unsigned long sz=-1;
  86. if( ioctlsocket( sock,FIONREAD,&sz ) ){ e=-1;return 0; }
  87. in_buf.resize( sz );in_get=0;
  88. int len=sizeof(in_addr);
  89. n=::recvfrom( sock,in_buf.begin(),sz,0,(sockaddr*)&in_addr,&len );
  90. if( n==SOCKET_ERROR ) continue; //{ e=-1;return 0; }
  91. in_buf.resize( n );
  92. return getMsgIP();
  93. }
  94. return 0;
  95. }
  96. //send, empty buffer
  97. int UDPStream::send( int ip,int port ){
  98. if( e ) return 0;
  99. int sz=out_buf.size();
  100. out_addr.sin_addr.S_un.S_addr=htonl( ip );
  101. out_addr.sin_port=htons( port ? port : addr.sin_port );
  102. int n=::sendto( sock,out_buf.begin(),sz,0,(sockaddr*)&out_addr,sizeof(out_addr) );
  103. if( n!=sz ) return e=-1;
  104. out_buf.clear();
  105. return sz;
  106. }
  107. int UDPStream::getIP(){
  108. return ntohl( addr.sin_addr.S_un.S_addr );
  109. }
  110. int UDPStream::getPort(){
  111. return ntohs( addr.sin_port );
  112. }
  113. int UDPStream::getMsgIP(){
  114. return ntohl( in_addr.sin_addr.S_un.S_addr );
  115. }
  116. int UDPStream::getMsgPort(){
  117. return ntohs( in_addr.sin_port );
  118. }
  119. class TCPStream : public bbStream{
  120. public:
  121. TCPStream( SOCKET s,TCPServer *t );
  122. ~TCPStream();
  123. int read( char *buff,int size );
  124. int write( const char *buff,int size );
  125. int avail();
  126. int eof();
  127. int getIP();
  128. int getPort();
  129. private:
  130. SOCKET sock;
  131. TCPServer *server;
  132. int e,ip,port;
  133. };
  134. class TCPServer{
  135. public:
  136. TCPServer( SOCKET S );
  137. ~TCPServer();
  138. TCPStream *accept();
  139. void remove( TCPStream *s );
  140. private:
  141. int e;
  142. SOCKET sock;
  143. set<TCPStream*> accepted_set;
  144. };
  145. TCPStream::TCPStream( SOCKET s,TCPServer *t ):sock(s),server(t),e(0){
  146. sockaddr_in addr;
  147. int len=sizeof(addr);
  148. if( getpeername( s,(sockaddr*)&addr,&len ) ){
  149. ip=port=0;
  150. return;
  151. }
  152. ip=ntohl(addr.sin_addr.S_un.S_addr);
  153. port=ntohs(addr.sin_port);
  154. }
  155. TCPStream::~TCPStream(){
  156. if( server ) server->remove( this );
  157. close( sock,e );
  158. }
  159. int TCPStream::read( char *buff,int size ){
  160. if( e ) return 0;
  161. char *b=buff,*l=buff+size;
  162. int tout;
  163. if( read_timeout ) tout=gx_runtime->getMilliSecs()+read_timeout;
  164. while( b<l ){
  165. int dt=0;
  166. if( read_timeout ){
  167. dt=tout-gx_runtime->getMilliSecs();
  168. if( dt<0 ) dt=0;
  169. }
  170. fd_set fd={ 1,sock };
  171. timeval tv={ dt/1000,(dt%1000)*1000 };
  172. int n=::select( 0,&fd,0,0,&tv );
  173. if( n!=1 ){ e=-1;break; }
  174. n=::recv( sock,b,l-b,0 );
  175. if( n==0 ){ e=1;break; }
  176. if( n==SOCKET_ERROR ){ e=-1;break; }
  177. b+=n;
  178. }
  179. return b-buff;
  180. }
  181. int TCPStream::write( const char *buff,int size ){
  182. if( e ) return 0;
  183. int n=::send( sock,buff,size,0 );
  184. if( n==SOCKET_ERROR ){ e=-1;return 0; }
  185. return n;
  186. }
  187. int TCPStream::avail(){
  188. unsigned long t;
  189. int n=::ioctlsocket( sock,FIONREAD,&t );
  190. if( n==SOCKET_ERROR ){ e=-1;return 0; }
  191. return t;
  192. }
  193. int TCPStream::eof(){
  194. if( e ) return e;
  195. fd_set fd={ 1,sock };
  196. timeval tv={ 0,0 };
  197. switch( ::select( 0,&fd,0,0,&tv ) ){
  198. case 0:break;
  199. case 1:if( !avail() ) e=1;break;
  200. default:e=-1;
  201. }
  202. return e;
  203. }
  204. int TCPStream::getIP(){
  205. return ip;
  206. }
  207. int TCPStream::getPort(){
  208. return port;
  209. }
  210. TCPServer::TCPServer( SOCKET s ):sock(s),e(0){
  211. }
  212. TCPServer::~TCPServer(){
  213. while( accepted_set.size() ) delete *accepted_set.begin();
  214. close( sock,e );
  215. }
  216. TCPStream *TCPServer::accept(){
  217. if( e ) return 0;
  218. fd_set fd={ 1,sock };
  219. timeval tv={ accept_timeout/1000,(accept_timeout%1000)*1000 };
  220. int n=::select( 0,&fd,0,0,&tv );
  221. if( n==0 ) return 0;
  222. if( n!=1 ){ e=-1;return 0; }
  223. SOCKET t=::accept( sock,0,0 );
  224. if( t==INVALID_SOCKET ){ e=-1;return 0; }
  225. TCPStream *s=d_new TCPStream( t,this );
  226. accepted_set.insert( s );
  227. return s;
  228. }
  229. void TCPServer::remove( TCPStream *s ){
  230. accepted_set.erase( s );
  231. }
  232. static inline void debugUDPStream( UDPStream *p ){
  233. if( debug && !udp_set.count(p) ){
  234. RTEX( "UDP Stream does not exist" );
  235. }
  236. }
  237. static inline void debugTCPStream( TCPStream *p ){
  238. if( debug && !tcp_set.count(p) ){
  239. RTEX( "TCP Stream does not exist" );
  240. }
  241. }
  242. static inline void debugTCPServer( TCPServer *p ){
  243. if( debug && !server_set.count(p) ){
  244. RTEX( "TCP Server does not exist" );
  245. }
  246. }
  247. static vector<int> host_ips;
  248. int bbCountHostIPs( BBStr *host ){
  249. host_ips.clear();
  250. HOSTENT *h=gethostbyname( host->c_str() );
  251. delete host;if( !h ) return 0;
  252. char **p=h->h_addr_list;
  253. while( char *t=*p++ ) host_ips.push_back( ntohl(*(int*)t) );
  254. return host_ips.size();
  255. }
  256. int bbHostIP( int index ){
  257. if( debug ){
  258. if( index<1 || index>host_ips.size() ){
  259. RTEX( "Host index out of range" );
  260. }
  261. }
  262. return host_ips[index-1];
  263. }
  264. UDPStream *bbCreateUDPStream( int port ){
  265. if( !socks_ok ) return 0;
  266. SOCKET s=::socket( AF_INET,SOCK_DGRAM,0 );
  267. if( s!=INVALID_SOCKET ){
  268. sockaddr_in addr={AF_INET,htons(port)};
  269. if( !::bind( s,(sockaddr*)&addr,sizeof(addr) ) ){
  270. UDPStream *p=d_new UDPStream( s );
  271. udp_set.insert( p );
  272. return p;
  273. }
  274. ::closesocket( s );
  275. }
  276. return 0;
  277. }
  278. void bbCloseUDPStream( UDPStream *p ){
  279. debugUDPStream( p );
  280. udp_set.erase( p );
  281. delete p;
  282. }
  283. int bbRecvUDPMsg( UDPStream *p ){
  284. debugUDPStream( p );
  285. return p->recv();
  286. }
  287. void bbSendUDPMsg( UDPStream *p,int ip,int port ){
  288. debugUDPStream( p );
  289. p->send( ip,port );
  290. }
  291. int bbUDPStreamIP( UDPStream *p ){
  292. debugUDPStream( p );
  293. return p->getIP();
  294. }
  295. int bbUDPStreamPort( UDPStream *p ){
  296. debugUDPStream( p );
  297. return p->getPort();
  298. }
  299. int bbUDPMsgIP( UDPStream *p ){
  300. debugUDPStream( p );
  301. return p->getMsgIP();
  302. }
  303. int bbUDPMsgPort( UDPStream *p ){
  304. debugUDPStream( p );
  305. return p->getMsgPort();
  306. }
  307. void bbUDPTimeouts( int rt ){
  308. recv_timeout=rt;
  309. }
  310. BBStr *bbDottedIP( int ip ){
  311. return d_new BBStr(
  312. itoa((ip>>24)&255)+"."+itoa((ip>>16)&255)+"."+
  313. itoa((ip>>8)&255)+"."+itoa(ip&255) );
  314. }
  315. static int findHostIP( const string &t ){
  316. int ip=inet_addr( t.c_str() );
  317. if( ip!=INADDR_NONE ) return ip;
  318. HOSTENT *h=gethostbyname( t.c_str() );
  319. if( !h ) return -1;
  320. char *p;
  321. for( char **list=h->h_addr_list;p=*list;++list ){
  322. return *(int*)p;
  323. }
  324. return 0;
  325. }
  326. TCPStream *bbOpenTCPStream( BBStr *server,int port,int local_port ){
  327. if( !socks_ok ){
  328. delete server;
  329. return 0;
  330. }
  331. int ip=findHostIP( *server );delete server;
  332. if( ip==-1 ) return 0;
  333. SOCKET s=::socket( AF_INET,SOCK_STREAM,0 );
  334. if( s!=INVALID_SOCKET ){
  335. if( local_port ){
  336. sockaddr_in addr={AF_INET,htons(local_port)};
  337. if( ::bind( s,(sockaddr*)&addr,sizeof(addr) ) ){
  338. ::closesocket( s );
  339. return 0;
  340. }
  341. }
  342. sockaddr_in addr={AF_INET,htons(port)};
  343. addr.sin_addr.S_un.S_addr=ip;
  344. if( !::connect( s,(sockaddr*)&addr,sizeof(addr) ) ){
  345. TCPStream *p=d_new TCPStream( s,0 );
  346. tcp_set.insert( p );
  347. return p;
  348. }
  349. ::closesocket( s );
  350. }
  351. return 0;
  352. }
  353. void bbCloseTCPStream( TCPStream *p ){
  354. debugTCPStream( p );
  355. tcp_set.erase( p );
  356. delete p;
  357. }
  358. TCPServer * bbCreateTCPServer( int port ){
  359. SOCKET s=::socket( AF_INET,SOCK_STREAM,0 );
  360. if( s!=INVALID_SOCKET ){
  361. sockaddr_in addr={AF_INET,htons(port)};
  362. if( !::bind( s,(sockaddr*)&addr,sizeof(addr) ) ){
  363. if( !::listen( s,SOMAXCONN ) ){
  364. TCPServer *p=d_new TCPServer( s );
  365. server_set.insert( p );
  366. return p;
  367. }
  368. }
  369. ::closesocket(s);
  370. }
  371. return 0;
  372. }
  373. void bbCloseTCPServer( TCPServer *p ){
  374. debugTCPServer( p );
  375. server_set.erase( p );
  376. delete p;
  377. }
  378. TCPStream * bbAcceptTCPStream( TCPServer *server ){
  379. debugTCPServer( server );
  380. if( !gx_runtime->idle() ) RTEX( 0 );
  381. if( TCPStream *tcp=server->accept() ){
  382. tcp_set.insert( tcp );
  383. return tcp;
  384. }
  385. return 0;
  386. }
  387. int bbTCPStreamIP( TCPStream *p ){
  388. debugTCPStream( p );
  389. return p->getIP();
  390. }
  391. int bbTCPStreamPort( TCPStream *p ){
  392. debugTCPStream( p );
  393. return p->getPort();
  394. }
  395. void bbTCPTimeouts( int rt,int at ){
  396. read_timeout=rt;
  397. accept_timeout=at;
  398. }
  399. bool sockets_create(){
  400. socks_ok=WSAStartup( 0x0101,&wsadata )==0;
  401. recv_timeout=0;
  402. read_timeout=10000;
  403. accept_timeout=0;
  404. return true;
  405. }
  406. bool sockets_destroy(){
  407. while( udp_set.size() ) bbCloseUDPStream( *udp_set.begin() );
  408. while( tcp_set.size() ) bbCloseTCPStream( *tcp_set.begin() );
  409. while( server_set.size() ) bbCloseTCPServer( *server_set.begin() );
  410. if( socks_ok ) WSACleanup();
  411. return true;
  412. }
  413. void sockets_link( void(*rtSym)(const char*,void*) ){
  414. rtSym( "$DottedIP%IP",bbDottedIP );
  415. rtSym( "%CountHostIPs$host_name",bbCountHostIPs );
  416. rtSym( "%HostIP%host_index",bbHostIP );
  417. rtSym( "%CreateUDPStream%port=0",bbCreateUDPStream );
  418. rtSym( "CloseUDPStream%udp_stream",bbCloseUDPStream );
  419. rtSym( "SendUDPMsg%udp_stream%dest_ip%dest_port=0",bbSendUDPMsg );
  420. rtSym( "%RecvUDPMsg%udp_stream",bbRecvUDPMsg );
  421. rtSym( "%UDPStreamIP%udp_stream",bbUDPStreamIP );
  422. rtSym( "%UDPStreamPort%udp_stream",bbUDPStreamPort );
  423. rtSym( "%UDPMsgIP%udp_stream",bbUDPMsgIP );
  424. rtSym( "%UDPMsgPort%udp_stream",bbUDPMsgPort );
  425. rtSym( "UDPTimeouts%recv_timeout",bbUDPTimeouts );
  426. rtSym( "%OpenTCPStream$server%server_port%local_port=0",bbOpenTCPStream );
  427. rtSym( "CloseTCPStream%tcp_stream",bbCloseTCPStream );
  428. rtSym( "%CreateTCPServer%port",bbCreateTCPServer );
  429. rtSym( "CloseTCPServer%tcp_server",bbCloseTCPServer );
  430. rtSym( "%AcceptTCPStream%tcp_server",bbAcceptTCPStream );
  431. rtSym( "%TCPStreamIP%tcp_stream",bbTCPStreamIP );
  432. rtSym( "%TCPStreamPort%tcp_stream",bbTCPStreamPort );
  433. rtSym( "TCPTimeouts%read_millis%accept_millis",bbTCPTimeouts );
  434. }