pipmsgsv.cxx (2792B)
1 /* 2 * 3 * C++ Portable Types Library (PTypes) 4 * Version 2.1.1 Released 27-Jun-2007 5 * 6 * Copyright (C) 2001-2007 Hovik Melikyan 7 * 8 * http://www.melikyan.com/ptypes/ 9 * 10 */ 11 12 #ifdef WIN32 13 # include <winsock2.h> 14 #else 15 # include <sys/time.h> 16 # include <sys/types.h> 17 # include <sys/socket.h> 18 # include <netinet/in.h> 19 # include <arpa/inet.h> 20 # include <netdb.h> 21 # include <unistd.h> 22 # include <time.h> 23 #endif 24 25 26 #include "pinet.h" 27 28 29 namespace ptypes { 30 31 32 // 33 // ipmsgserver: IPv4 UDP socket server 34 // 35 36 37 ipmsgserver::ipmsgserver() 38 : ipsvbase(SOCK_DGRAM), ippeerinfo(), handle(invhandle) 39 { 40 } 41 42 43 ipmsgserver::~ipmsgserver() 44 { 45 close(); 46 } 47 48 49 void ipmsgserver::dobind(ipbindinfo* b) 50 { 51 sockaddr_in sa; 52 memset(&sa, 0, sizeof(sa)); 53 sa.sin_family = AF_INET; 54 sa.sin_port = htons(ushort(b->get_port())); 55 sa.sin_addr.s_addr = b->get_ip(); 56 if (::bind(b->handle, (sockaddr*)&sa, sizeof(sa)) != 0) 57 error(*b, usockerrno(), "Couldn't bind address"); 58 } 59 60 61 void ipmsgserver::close() 62 { 63 if (!active) 64 return; 65 ipsvbase::close(); 66 handle = invhandle; 67 ippeerinfo::clear(); 68 } 69 70 71 bool ipmsgserver::poll(int i, int timeout) 72 { 73 if (!active) 74 open(); 75 return dopoll(&i, timeout); 76 } 77 78 79 int ipmsgserver::receive(char* buf, int count) 80 { 81 if (!active) 82 open(); 83 ippeerinfo::clear(); 84 85 // determine which socket has pending data 86 int i = -1; 87 if (!dopoll(&i, -1)) 88 error(*this, EINVAL, "Couldn't read"); 89 ipbindinfo* b = (ipbindinfo*)addrlist[i]; 90 handle = b->handle; 91 92 // read data 93 sockaddr_in sa; 94 psocklen len = sizeof(sa); 95 int result = ::recvfrom(handle, buf, count, 0, (sockaddr*)&sa, &len); 96 if (result < 0) 97 error(*b, usockerrno(), "Couldn't read"); 98 99 // set up peer ip and port 100 ip = sa.sin_addr.s_addr; 101 port = ntohs(sa.sin_port); 102 return result; 103 } 104 105 106 string ipmsgserver::receive(int max) 107 { 108 string result; 109 setlength(result, max); 110 int numread = receive(pchar(pconst(result)), max); 111 setlength(result, numread); 112 return result; 113 } 114 115 116 void ipmsgserver::send(const char* buf, int count) 117 { 118 if (!active || handle == invhandle || ip == ipnone) 119 error(*this, EINVAL, "Couldn't write"); // must receive() first 120 121 sendto(buf, count, get_ip(), get_port()); 122 } 123 124 125 void ipmsgserver::sendto(const char* buf, int count, ipaddress ip, int port) 126 { 127 if (!active || handle == invhandle || ip == ipnone) 128 error(*this, EINVAL, "Couldn't write"); // must receive() first 129 130 sockaddr_in sa; 131 memset(&sa, 0, sizeof(sa)); 132 sa.sin_family = AF_INET; 133 sa.sin_port = htons(ushort(port)); 134 sa.sin_addr.s_addr = ip; 135 if (::sendto(handle, buf, count, 0, (sockaddr*)&sa, sizeof(sa)) < 0) 136 error(*this, usockerrno(), "Couldn't write"); 137 } 138 139 140 }