PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/OpenSLP_0-6-0/openslp/libslp/libslp_network.c

#
C | 332 lines | 209 code | 32 blank | 91 comment | 27 complexity | 7b3cbf3bf6f72390509a3685760b4075 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: slplib_network.c */
  7. /* */
  8. /* Abstract: Implementation for INTERNAL 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.h"
  35. #include "libslp.h"
  36. /*=========================================================================*/
  37. struct sockaddr_in G_SlpdAddr;
  38. int G_SlpdSocket = -1;
  39. /*=========================================================================*/
  40. /*=========================================================================*/
  41. int NetworkGetSlpdSocket(struct sockaddr* peeraddr, int peeraddrlen)
  42. /* Connects to slpd. Will not block. */
  43. /* */
  44. /* peeraddr (OUT) receives the address of the socket */
  45. /* */
  46. /* peeraddrlen (OUT) receives the length of the socket address */
  47. /* */
  48. /* Returns - -1 if connection can not be made */
  49. /*=========================================================================*/
  50. {
  51. int lowat;
  52. if(G_SlpdSocket == -1)
  53. {
  54. G_SlpdSocket = socket(AF_INET,SOCK_STREAM,0);
  55. if(G_SlpdSocket >= 0)
  56. {
  57. G_SlpdAddr.sin_family = AF_INET;
  58. G_SlpdAddr.sin_port = htons(SLP_RESERVED_PORT);
  59. G_SlpdAddr.sin_addr.s_addr = htonl(LOOPBACK_ADDRESS);
  60. if(connect(G_SlpdSocket,(struct sockaddr*)&G_SlpdAddr,sizeof(G_SlpdAddr)) == 0)
  61. {
  62. /* set the receive and send buffer low water mark to 18 bytes
  63. (the length of the smallest slpv2 message) */
  64. lowat = 18;
  65. setsockopt(G_SlpdSocket,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat));
  66. setsockopt(G_SlpdSocket,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat));
  67. if(peeraddrlen >= sizeof(G_SlpdAddr))
  68. {
  69. memcpy(peeraddr,&G_SlpdAddr,sizeof(G_SlpdAddr));
  70. }
  71. else
  72. {
  73. memcpy(peeraddr,&G_SlpdAddr,peeraddrlen);
  74. }
  75. }
  76. else
  77. {
  78. /* Could not connect to the slpd through the loopback */
  79. close(G_SlpdSocket);
  80. G_SlpdSocket = -1;
  81. }
  82. }
  83. }
  84. else
  85. {
  86. if(peeraddrlen >= sizeof(G_SlpdAddr))
  87. {
  88. memcpy(peeraddr,&G_SlpdAddr,sizeof(G_SlpdAddr));
  89. }
  90. else
  91. {
  92. memcpy(peeraddr,&G_SlpdAddr,peeraddrlen);
  93. }
  94. }
  95. return G_SlpdSocket;
  96. }
  97. /*=========================================================================*/
  98. void NetworkCloseSlpdSocket()
  99. /*=========================================================================*/
  100. {
  101. close(G_SlpdSocket);
  102. G_SlpdSocket = -1;
  103. }
  104. /*=========================================================================*/
  105. SLPError NetworkSendMessage(int sockfd,
  106. SLPBuffer buf,
  107. struct timeval* timeout,
  108. struct sockaddr* peeraddr,
  109. int peeraddrlen)
  110. /* Returns - SLP_OK, SLP_NETWORK_TIMEOUT, SLP_NETWORK_ERROR, or */
  111. /* SLP_PARSE_ERROR. */
  112. /*=========================================================================*/
  113. {
  114. fd_set writefds;
  115. int xferbytes;
  116. SLPError result = SLP_OK;
  117. while(buf->curpos < buf->end)
  118. {
  119. FD_ZERO(&writefds);
  120. FD_SET(sockfd, &writefds);
  121. xferbytes = select(sockfd + 1, 0, &writefds, 0, timeout);
  122. if(xferbytes > 0)
  123. {
  124. xferbytes = sendto(sockfd,
  125. buf->curpos,
  126. buf->end - buf->curpos,
  127. 0,
  128. peeraddr,
  129. sizeof(struct sockaddr_in));
  130. if(xferbytes > 0)
  131. {
  132. buf->curpos = buf->curpos + xferbytes;
  133. }
  134. else
  135. {
  136. result = SLP_NETWORK_ERROR;
  137. break;
  138. }
  139. }
  140. else if(xferbytes == 0)
  141. {
  142. result = SLP_NETWORK_TIMED_OUT;
  143. break;
  144. }
  145. else
  146. {
  147. result = SLP_NETWORK_ERROR;
  148. break;
  149. }
  150. }
  151. return result;
  152. }
  153. /*=========================================================================*/
  154. SLPError NetworkRecvMessage(int sockfd,
  155. SLPBuffer buf,
  156. struct timeval* timeout,
  157. struct sockaddr* peeraddr,
  158. int* peeraddrlen)
  159. /* Receives a message */
  160. /* */
  161. /* Returns - SLP_OK, SLP_NETWORK_TIMEOUT, SLP_NETWORK_ERROR, or */
  162. /* SLP_PARSE_ERROR. */
  163. /*=========================================================================*/
  164. {
  165. SLPError result = SLP_OK;
  166. int xferbytes;
  167. fd_set readfds;
  168. char peek[16];
  169. /*---------------------------------------------------------------*/
  170. /* take a peek at the packet to get version and size information */
  171. /*---------------------------------------------------------------*/
  172. FD_ZERO(&readfds);
  173. FD_SET(sockfd, &readfds);
  174. xferbytes = select(sockfd + 1, &readfds, 0 , 0, timeout);
  175. if(xferbytes > 0)
  176. {
  177. xferbytes = recvfrom(sockfd,
  178. peek,
  179. 16,
  180. MSG_PEEK,
  181. peeraddr,
  182. peeraddrlen);
  183. if(xferbytes <= 0)
  184. {
  185. result = SLP_NETWORK_ERROR;
  186. }
  187. }
  188. else if(xferbytes == 0)
  189. {
  190. result = SLP_NETWORK_TIMED_OUT;
  191. }
  192. else
  193. {
  194. result = SLP_NETWORK_ERROR;
  195. }
  196. /*---------------------------------------*/
  197. /* return now if peek was not successful */
  198. /*---------------------------------------*/
  199. if(result) return result;
  200. /*------------------------------*/
  201. /* Read the rest of the message */
  202. /*------------------------------*/
  203. /* check the version */
  204. if(*peek == 2)
  205. {
  206. /* allocate the recvmsg big enough for the whole message */
  207. if(SLPBufferRealloc(buf, AsUINT24(peek + 2)))
  208. {
  209. while(buf->curpos < buf->end)
  210. {
  211. FD_ZERO(&readfds);
  212. FD_SET(sockfd, &readfds);
  213. xferbytes = select(sockfd + 1, &readfds, 0 , 0, timeout);
  214. if(xferbytes > 0)
  215. {
  216. xferbytes = recv(sockfd,
  217. buf->curpos,
  218. buf->end - buf->curpos,
  219. 0);
  220. if(xferbytes > 0)
  221. {
  222. buf->curpos = buf->curpos + xferbytes;
  223. }
  224. else
  225. {
  226. result = SLP_NETWORK_ERROR;
  227. break;
  228. }
  229. }
  230. else if(xferbytes == 0)
  231. {
  232. result = SLP_NETWORK_TIMED_OUT;
  233. break;
  234. }
  235. else
  236. {
  237. result = SLP_NETWORK_ERROR;
  238. break;
  239. }
  240. } /* end of main read while. */
  241. }
  242. else
  243. {
  244. result = SLP_MEMORY_ALLOC_FAILED;
  245. }
  246. }
  247. else
  248. {
  249. result = SLP_PARSE_ERROR;
  250. }
  251. return result;
  252. }
  253. /*=========================================================================*/
  254. int NetworkConnectToDA(struct sockaddr_in* peeraddr)
  255. /*=========================================================================*/
  256. {
  257. /*
  258. int lowat;
  259. lowat = 18;
  260. setsockopt(G_SlpdSocket,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat));
  261. setsockopt(G_SlpdSocket,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat));
  262. */
  263. return -1;
  264. }
  265. /*=========================================================================*/
  266. int NetworkConnectToSlpMulticast(struct sockaddr_in* peeraddr)
  267. /* Creates a socket and connects it to the SLP multicast address */
  268. /* */
  269. /* Returns - Valid file descriptor on success, -1 on failure w/ errno set.*/
  270. /*=========================================================================*/
  271. {
  272. int sockfd;
  273. int ttl;
  274. /* connect to the SA (through the loopback) */
  275. sockfd = socket(AF_INET,SOCK_DGRAM,0);
  276. if(sockfd >= 0)
  277. {
  278. peeraddr->sin_family = AF_INET;
  279. peeraddr->sin_port = htons(SLP_RESERVED_PORT);
  280. peeraddr->sin_addr.s_addr = htonl(SLP_MCAST_ADDRESS);
  281. /* TODO: Set TTL from conf file*/
  282. ttl = 8;
  283. setsockopt(sockfd,
  284. IPPROTO_IP,
  285. IP_MULTICAST_TTL,
  286. &ttl,
  287. sizeof(ttl));
  288. }
  289. return sockfd;
  290. }
  291. /*=========================================================================*/
  292. int NetworkConnectToSlpBroadcast(struct sockaddr_in* peeraddr)
  293. /* Creates a socket and connects it to the SLP multicast address */
  294. /* */
  295. /* Returns - Valid file descriptor on success, -1 on failure w/ errno set.*/
  296. /*=========================================================================*/
  297. {
  298. /* TODO: implement broadcast later */
  299. return -1;
  300. }