PageRenderTime 54ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/OpenSLP_0-7-6/openslp/common/slp_network.c

#
C | 382 lines | 259 code | 32 blank | 91 comment | 28 complexity | 2f2d75ce29ef72f87e81daf8238eca5b MD5 | raw file
Possible License(s): BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /***************************************************************************/
  2. /* */
  3. /* Project: OpenSLP - OpenSource implementation of Service Location */
  4. /* Protocol */
  5. /* */
  6. /* File: slp_network.c */
  7. /* */
  8. /* Abstract: Implementation for functions that are related */
  9. /* network (and ipc) communication. */
  10. /* */
  11. /*-------------------------------------------------------------------------*/
  12. /* */
  13. /* Copyright (c) 1995, 1999 Caldera Systems, Inc. */
  14. /* */
  15. /* This program is free software; you can redistribute it and/or modify it */
  16. /* under the terms of the GNU Lesser General Public License as published */
  17. /* by the Free Software Foundation; either version 2.1 of the License, or */
  18. /* (at your option) any later version. */
  19. /* */
  20. /* This program is distributed in the hope that it will be useful, */
  21. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  22. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  23. /* GNU Lesser General Public License for more details. */
  24. /* */
  25. /* You should have received a copy of the GNU Lesser General Public */
  26. /* License along with this program; see the file COPYING. If not, */
  27. /* please obtain a copy from http://www.gnu.org/copyleft/lesser.html */
  28. /* */
  29. /*-------------------------------------------------------------------------*/
  30. /* */
  31. /* Please submit patches to http://www.openslp.org */
  32. /* */
  33. /***************************************************************************/
  34. #include <slp_network.h>
  35. /*=========================================================================*/
  36. int SLPNetworkConnectStream(struct sockaddr_in* peeraddr,
  37. struct timeval* timeout)
  38. /* Connect a TCP stream to the specified peer */
  39. /* */
  40. /* peeraddr (IN) pointer to the peer to connect to */
  41. /* */
  42. /* timeout (IN) pointer to the maximum time to spend connecting */
  43. /* */
  44. /* returns: a connected socket or -1 */
  45. /*=========================================================================*/
  46. {
  47. #ifdef WIN32
  48. char lowat;
  49. #else
  50. int lowat;
  51. #endif
  52. int result;
  53. /* TODO: Make this connect non-blocking so that it will timeout */
  54. result = socket(AF_INET,SOCK_STREAM,0);
  55. if(result >= 0)
  56. {
  57. if(connect(result,
  58. (struct sockaddr*)peeraddr,
  59. sizeof(struct sockaddr_in)) == 0)
  60. {
  61. /* set the receive and send buffer low water mark to 18 bytes
  62. (the length of the smallest slpv2 message) */
  63. lowat = 18;
  64. setsockopt(result,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat));
  65. setsockopt(result,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat));
  66. return result;;
  67. }
  68. else
  69. {
  70. close(result);
  71. result = -1;
  72. }
  73. }
  74. return result;
  75. }
  76. /*=========================================================================*/
  77. int SLPNetworkConnectToMulticast(struct sockaddr_in* peeraddr, int ttl)
  78. /* Creates a socket and provides a peeraddr to send to */
  79. /* */
  80. /* peeraddr (OUT) pointer to receive the connected DA's address */
  81. /* */
  82. /* ttl (IN) ttl for the mcast socket */
  83. /* */
  84. /* Returns Valid socket or -1 if no DA connection can be made */
  85. /*=========================================================================*/
  86. {
  87. int sockfd;
  88. #if defined(linux)
  89. int optarg;
  90. #else
  91. /* Solaris and Tru64 expect a unsigned char parameter */
  92. unsigned char optarg;
  93. #endif
  94. #ifdef WIN32
  95. BOOL Reuse = TRUE;
  96. int TTLArg;
  97. struct sockaddr_in mysockaddr;
  98. memset(&mysockaddr, 0, sizeof(mysockaddr));
  99. mysockaddr.sin_family = AF_INET;
  100. mysockaddr.sin_port = 0;
  101. #endif
  102. /* setup multicast socket */
  103. sockfd = socket(AF_INET,SOCK_DGRAM,0);
  104. if(sockfd >= 0)
  105. {
  106. peeraddr->sin_family = AF_INET;
  107. peeraddr->sin_port = htons(SLP_RESERVED_PORT);
  108. peeraddr->sin_addr.s_addr = htonl(SLP_MCAST_ADDRESS);
  109. optarg = ttl;
  110. #ifdef WIN32
  111. TTLArg = ttl;
  112. if (setsockopt(sockfd,
  113. SOL_SOCKET,
  114. SO_REUSEADDR,
  115. (const char *)&Reuse,
  116. sizeof(Reuse)) ||
  117. bind(sockfd,
  118. (struct sockaddr *)&mysockaddr,
  119. sizeof(mysockaddr)) ||
  120. setsockopt(sockfd,
  121. IPPROTO_IP,
  122. IP_MULTICAST_TTL,
  123. (char *)&TTLArg,
  124. sizeof(TTLArg)))
  125. {
  126. return -1;
  127. }
  128. #else
  129. if(setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_TTL,&optarg,sizeof(optarg)))
  130. {
  131. return -1;
  132. }
  133. #endif
  134. }
  135. return sockfd;
  136. }
  137. /*=========================================================================*/
  138. int SLPNetworkConnectToBroadcast(struct sockaddr_in* peeraddr)
  139. /* Creates a socket and provides a peeraddr to send to */
  140. /* */
  141. /* peeraddr (OUT) pointer to receive the connected DA's address */
  142. /* */
  143. /* Returns Valid socket or -1 if no DA connection can be made */
  144. /*=========================================================================*/
  145. {
  146. int sockfd;
  147. #ifdef WIN32
  148. char on = 1;
  149. #else
  150. int on = 1;
  151. #endif
  152. /* setup broadcast */
  153. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  154. if(sockfd >= 0)
  155. {
  156. peeraddr->sin_family = AF_INET;
  157. peeraddr->sin_port = htons(SLP_RESERVED_PORT);
  158. peeraddr->sin_addr.s_addr = htonl(SLP_BCAST_ADDRESS);
  159. if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)))
  160. {
  161. return -1;
  162. }
  163. }
  164. return sockfd;
  165. }
  166. /*=========================================================================*/
  167. int SLPNetworkSendMessage(int sockfd,
  168. SLPBuffer buf,
  169. struct sockaddr_in* peeraddr,
  170. struct timeval* timeout)
  171. /* Sends a message */
  172. /* */
  173. /* Returns - zero on success non-zero on failure */
  174. /* */
  175. /* errno EPIPE error during write */
  176. /* ETIME read timed out */
  177. /*=========================================================================*/
  178. {
  179. fd_set writefds;
  180. int xferbytes;
  181. int flags = 0;
  182. #if defined(MSG_NOSIGNAL)
  183. flags = MSG_NOSIGNAL;
  184. #endif
  185. buf->curpos = buf->start;
  186. while(buf->curpos < buf->end)
  187. {
  188. FD_ZERO(&writefds);
  189. FD_SET(sockfd, &writefds);
  190. xferbytes = select(sockfd + 1, 0, &writefds, 0, timeout);
  191. if(xferbytes > 0)
  192. {
  193. xferbytes = sendto(sockfd,
  194. buf->curpos,
  195. buf->end - buf->curpos,
  196. flags,
  197. (struct sockaddr *)peeraddr,
  198. sizeof(struct sockaddr_in));
  199. if(xferbytes > 0)
  200. {
  201. buf->curpos = buf->curpos + xferbytes;
  202. }
  203. else
  204. {
  205. #ifndef WIN32
  206. errno = EPIPE;
  207. #endif
  208. return -1;
  209. }
  210. }
  211. else if(xferbytes == 0)
  212. {
  213. /* timed out */
  214. #ifndef WIN32
  215. errno = ETIMEDOUT;
  216. #endif
  217. return -1;
  218. }
  219. else
  220. {
  221. #ifndef WIN32
  222. errno = EPIPE;
  223. #endif
  224. return -1;
  225. }
  226. }
  227. return 0;
  228. }
  229. /*=========================================================================*/
  230. int SLPNetworkRecvMessage(int sockfd,
  231. SLPBuffer* buf,
  232. struct sockaddr_in* peeraddr,
  233. struct timeval* timeout)
  234. /* Receives a message */
  235. /* */
  236. /* Returns - zero on success, non-zero on failure */
  237. /* */
  238. /* errno ENOTCONN error during read */
  239. /* ETIME read timed out */
  240. /* ENOMEM out of memory */
  241. /* EINVAL parse error */
  242. /*=========================================================================*/
  243. {
  244. int xferbytes;
  245. fd_set readfds;
  246. char peek[16];
  247. int peeraddrlen = sizeof(struct sockaddr_in);
  248. /*---------------------------------------------------------------*/
  249. /* take a peek at the packet to get version and size information */
  250. /*---------------------------------------------------------------*/
  251. FD_ZERO(&readfds);
  252. FD_SET(sockfd, &readfds);
  253. xferbytes = select(sockfd + 1, &readfds, 0 , 0, timeout);
  254. if(xferbytes > 0)
  255. {
  256. xferbytes = recvfrom(sockfd,
  257. peek,
  258. 16,
  259. MSG_PEEK,
  260. (struct sockaddr *)peeraddr,
  261. &peeraddrlen);
  262. if(xferbytes <= 0)
  263. {
  264. #ifdef WIN32
  265. if (WSAGetLastError() != WSAEMSGSIZE)
  266. {
  267. return -1;
  268. }
  269. #else
  270. errno = ENOTCONN;
  271. return -1;
  272. #endif
  273. }
  274. }
  275. else if(xferbytes == 0)
  276. {
  277. #ifndef WIN32
  278. errno = ETIMEDOUT;
  279. #endif
  280. return -1;
  281. }
  282. else
  283. {
  284. #ifndef WIN32
  285. errno = ENOTCONN;
  286. #endif
  287. return -1;
  288. }
  289. /*------------------------------*/
  290. /* Read the rest of the message */
  291. /*------------------------------*/
  292. /* check the version */
  293. if(*peek == 2)
  294. {
  295. /* allocate the recvmsg big enough for the whole message */
  296. *buf = SLPBufferRealloc(*buf, AsUINT24(peek + 2));
  297. if(*buf)
  298. {
  299. while((*buf)->curpos < (*buf)->end)
  300. {
  301. FD_ZERO(&readfds);
  302. FD_SET(sockfd, &readfds);
  303. xferbytes = select(sockfd + 1, &readfds, 0 , 0, timeout);
  304. if(xferbytes > 0)
  305. {
  306. xferbytes = recv(sockfd,
  307. (*buf)->curpos,
  308. (*buf)->end - (*buf)->curpos,
  309. 0);
  310. if(xferbytes > 0)
  311. {
  312. (*buf)->curpos = (*buf)->curpos + xferbytes;
  313. }
  314. else
  315. {
  316. #ifndef WIN32
  317. errno = ENOTCONN;
  318. #endif
  319. return -1;
  320. }
  321. }
  322. else if(xferbytes == 0)
  323. {
  324. #ifndef WIN32
  325. errno = ETIMEDOUT;
  326. #endif
  327. return -1;
  328. }
  329. else
  330. {
  331. #ifndef WIN32
  332. errno = ENOTCONN;
  333. #endif
  334. return -1;
  335. }
  336. } /* end of main read while. */
  337. }
  338. else
  339. {
  340. errno = ENOMEM;
  341. return -1;
  342. }
  343. }
  344. else
  345. {
  346. errno = EINVAL;
  347. return -1;
  348. }
  349. return 0;
  350. }