alc_socket.c

Go to the documentation of this file.
00001 
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <string.h>
00038 #include <sys/types.h>
00039 
00040 #ifdef _MSC_VER
00041 #include <io.h>
00042 #else
00043 #include <sys/socket.h>
00044 #include <netdb.h>
00045 #include <netinet/in.h>
00046 #include <arpa/inet.h>
00047 #include <net/if.h>
00048 #include <unistd.h>
00049 #endif
00050 
00051 #include "alc_socket.h"
00052 
00060 int error_socket() {
00061 #ifdef _MSC_VER
00062     return WSAGetLastError();
00063 #else
00064     return errno;
00065 #endif
00066 }
00067 
00077 #ifdef _MSC_VER
00078 int close_socket(SOCKET a_socket) {
00079     return closesocket(a_socket);
00080 #else
00081 int close_socket(int a_socket) {
00082     return close(a_socket);
00083 #endif
00084 }
00085 
00086 int init_alc_socket(alc_channel_t *ch) {
00087         
00088   int receiver_socket_buffer_size = RECEIVER_SOCKET_BUFFER_SIZE;
00089   int ttl;
00090   int loop;
00091   int reuse;
00092   int mode;
00093   int addr_type;
00094   struct addrinfo hints, *local;
00095   struct in_addr if_addr;       /* interface IP address for IPv4 multicast */
00096   int return_value;  
00097   
00098 #if defined(LINUX) && defined(SSM)
00099   struct sockaddr_in6 source;
00100 #endif
00101         
00102   local = NULL;
00103   mode = ch->s->mode;
00104   addr_type = ch->s->addr_type;
00105   
00106   if(mode == SENDER) {
00107     
00108     if((ch->tx_sock  = socket(ch->s->addr_family, SOCK_DGRAM, 0)) < 0) {
00109           printf("socket failed with: %d\n", error_socket());
00110       fflush(stdout);
00111       return -1;
00112     }
00113     
00114     memset(&hints, 0, sizeof(hints));
00115     hints.ai_family = ch->s->addr_family;
00116     hints.ai_socktype = SOCK_DGRAM;
00117     
00118     /* ch->addrinfo is used in sendto function */
00119     
00120     if((return_value = getaddrinfo(ch->addr, ch->port, &hints, &ch->addrinfo)) != 0) {
00121 #ifdef _MSC_VER
00122       printf("getaddrinfo failed: %d\n", error_socket());
00123 #else
00124       if(return_value == EAI_SYSTEM) {
00125                 printf("getaddrinfo failed: %d\n", error_socket());
00126       }
00127           else{
00128                 printf("getaddrinfo failed: %d %s\n", return_value, gai_strerror(return_value));
00129       }
00130 #endif
00131           fflush(stdout);       
00132       close_socket(ch->tx_sock);
00133       return -1;
00134     }
00135     
00136     /* Bind the socket to right interface */
00137     
00138     if(ch->intface != NULL) {
00139       
00140       if((((ch->s->addr_family == PF_INET6)) || (addr_type == 1))) {
00141         
00142                 if((return_value = getaddrinfo(ch->intface, 0, &hints, &local)) != 0) {
00143 #ifdef _MSC_VER
00144                         printf("getaddrinfo failed: %d\n", error_socket());
00145 #else
00146                         if(return_value == EAI_SYSTEM) {
00147                                 printf("getaddrinfo failed: %d\n", error_socket());
00148                         }
00149                         else{
00150                                 printf("getaddrinfo failed: %d %s\n", return_value, gai_strerror(return_value));
00151                         }       
00152 #endif
00153                         fflush(stdout);
00154                         close_socket(ch->tx_sock);
00155                         return -1;
00156                 }
00157         
00158                 if(bind(ch->tx_sock, local->ai_addr, local->ai_addrlen) < 0) {
00159                         printf("bind failed: %d\n", error_socket());
00160                         fflush(stdout);
00161                         close_socket(ch->tx_sock);
00162                         return -1;
00163                 }
00164       }
00165       else if(((ch->s->addr_family == PF_INET) && (addr_type == 0))) {
00166                 /* does not work without this interface setting */
00167                 if_addr.s_addr = inet_addr(ch->intface);
00168         
00169                 /* specify multicast interface */
00170                 if(setsockopt(ch->tx_sock, IPPROTO_IP, IP_MULTICAST_IF, 
00171                       (char*)&if_addr.s_addr, sizeof(if_addr.s_addr)) < 0 ) {
00172           
00173                         printf("setsockopt (IP_MULTICAST_IF) failed: %d\n", error_socket());
00174                         fflush(stdout);
00175                         close_socket(ch->tx_sock);
00176                         return -1;
00177                 }
00178       }
00179     }
00180     
00181     if(addr_type == 0) {
00182       
00183       /* TTL */
00184       ttl = min(ch->s->def_ttl, 255);
00185       
00186       if(ch->s->addr_family == PF_INET) {
00187         
00188                 if(setsockopt(ch->tx_sock, IPPROTO_IP, IP_MULTICAST_TTL, 
00189                       (char *)&ttl, sizeof(ttl)) < 0 ) {
00190                         printf("setsockopt (IP_MULTICAST_TTL) failed: %d\n", error_socket());
00191                         fflush(stdout);
00192                         close_socket(ch->tx_sock);
00193                         return -1;
00194                 }
00195       }
00196       else if(ch->s->addr_family == PF_INET6) {
00197         
00198                 if(setsockopt(ch->tx_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 
00199                       (char *)&ttl, sizeof(ttl)) < 0 ) {
00200                         printf("setsockopt (IPV6_MULTICAST_HOPS) failed: %d\n", error_socket());
00201                         fflush(stdout);
00202                         close_socket(ch->tx_sock);
00203                         return -1;
00204                 }
00205       } 
00206       
00207       /* Loopback (doesn't work in Windows, even if loop = 0, data is looped back) */
00208       /* set to 0, when you don't have to do testing any more */
00209       loop = 1;
00210       
00211       if(ch->s->addr_family == PF_INET) {
00212         
00213                 if(setsockopt(ch->tx_sock, IPPROTO_IP, IP_MULTICAST_LOOP, 
00214                       (char *)&loop, sizeof(loop)) != 0) {
00215                         printf("setsockopt (IP_MULTICAST_LOOP) failed: %d\n", error_socket());
00216                         fflush(stdout);
00217                         close_socket(ch->tx_sock);
00218                         return -1;
00219                 }
00220       }
00221       else if(ch->s->addr_family == PF_INET6) {
00222         
00223                 if(setsockopt(ch->tx_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 
00224                       (char *)&loop, sizeof(loop)) != 0) {
00225                         printf("setsockopt (IPV6_MULTICAST_LOOP) failed: %d\n", error_socket());
00226                         fflush(stdout);
00227                         close_socket(ch->tx_sock);
00228                         return -1;
00229                 }
00230       }
00231     }
00232     
00233     if(local != NULL) {
00234       freeaddrinfo(local);
00235     }
00236   }
00237   
00238   if(mode == RECEIVER) {
00239     
00240     if((ch->rx_sock = socket(ch->s->addr_family, SOCK_DGRAM, 0)) < 0) {
00241       printf("socket failed with: %d\n", error_socket());
00242       fflush(stdout);
00243       return -1;
00244     }
00245     
00246     memset(&hints, 0, sizeof(hints));
00247     hints.ai_family = ch->s->addr_family;
00248     hints.ai_socktype = SOCK_DGRAM;
00249     hints.ai_flags = AI_PASSIVE;
00250     
00251 #ifdef _MSC_VER
00252         if((return_value = getaddrinfo(ch->intface, ch->port, &hints, &ch->addrinfo)) != 0) {
00253 #else
00254         if((return_value = getaddrinfo(ch->addr, ch->port, &hints, &ch->addrinfo)) != 0) {
00255 #endif
00256 
00257 #ifdef _MSC_VER
00258       printf("getaddrinfo failed: %d\n", error_socket());
00259 #else
00260       if(return_value == EAI_SYSTEM) {
00261                 printf("getaddrinfo failed: %d\n", error_socket());
00262       }
00263           else{
00264                 printf("getaddrinfo failed: %d %s\n", return_value, gai_strerror(return_value));
00265       }
00266       
00267 #endif
00268           fflush(stdout);
00269           close_socket(ch->rx_sock);
00270       return -1;
00271         }
00272 
00273         reuse = 1;
00274 
00275     if(setsockopt(ch->rx_sock, SOL_SOCKET, SO_REUSEADDR,
00276                   (char *)&reuse, sizeof(reuse)) < 0 ) {
00277       printf("setsockopt (SO_REUSEADDR) failed: %d\n", error_socket());
00278           fflush(stdout);
00279       close_socket(ch->rx_sock);
00280       return -1;
00281     }
00282 
00283     if(setsockopt(ch->rx_sock, SOL_SOCKET, SO_RCVBUF, (char *)&receiver_socket_buffer_size, sizeof(int))) {
00284       printf("setsockopt (SO_RCVBUF) failed: %d\n", error_socket());
00285           fflush(stdout);
00286       close_socket(ch->rx_sock);
00287       return -1;
00288     }
00289     
00290     if(bind(ch->rx_sock, ch->addrinfo->ai_addr, ch->addrinfo->ai_addrlen) < 0) {
00291 
00292       printf("bind failed: %d\n", error_socket());
00293           fflush(stdout);
00294       close_socket(ch->rx_sock);
00295       return -1;
00296     }
00297     
00298     if(addr_type == 0) {
00299       if(ch->s->addr_family == PF_INET) {
00300         
00301                 memset((void *)&ch->remote, 0, sizeof(ch->remote));
00302                 
00303                 ch->remote.sin_addr.s_addr = inet_addr(ch->addr);
00304                 ch->remote.sin_port = (unsigned short)atoi(ch->port);
00305                 ch->remote.sin_family = ch->s->addr_family;
00306       }
00307       else if(ch->s->addr_family == PF_INET6) {
00308         
00309                 memset((void *)&ch->remote6, 0, sizeof(ch->remote6));
00310 #ifdef _MSC_VER
00311                 WSAStringToAddress((char*)ch->addr, PF_INET6, NULL, (struct sockaddr*)&ch->remote6,
00312                            &ch->addrinfo->ai_addrlen);
00313 #else
00314                 inet_pton(PF_INET6, ch->addr, &ch->remote6.sin6_addr);
00315 #endif
00316                 ch->remote6.sin6_port = (unsigned short)atoi(ch->port);
00317                 ch->remote6.sin6_family = ch->s->addr_family;
00318       }
00319     }
00320     
00321     if(addr_type == 0) {
00322       
00323       /* Join the multicast group */
00324       
00325       if(ch->s->addr_family == PF_INET) {
00326         
00327 #ifdef SSM
00328         if(ch->s->ssm) {
00329           ch->source_imr.imr_multiaddr.s_addr = ch->remote.sin_addr.s_addr;
00330           
00331           if(ch->intface == NULL) {
00332             ch->source_imr.imr_interface.s_addr = htonl(INADDR_ANY);
00333           }
00334           else {
00335             ch->source_imr.imr_interface.s_addr = inet_addr(ch->intface);
00336           }
00337           
00338           ch->source_imr.imr_sourceaddr.s_addr = inet_addr(ch->s->src_addr);
00339           
00340           if(setsockopt(ch->rx_sock, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
00341                         (char *)&ch->source_imr, sizeof(ch->source_imr)) < 0) {
00342             printf("setsockopt (IP_ADD_SOURCE_MEMBERSHIP) failed: %d\n", error_socket());
00343             fflush(stdout);
00344                 close_socket(ch->rx_sock);
00345             return -1;
00346           }
00347         }
00348         else {
00349           ch->imr.imr_multiaddr.s_addr = ch->remote.sin_addr.s_addr;
00350           
00351           if(ch->intface == NULL) {
00352             ch->imr.imr_interface.s_addr = htonl(INADDR_ANY);
00353           }
00354           else {
00355             ch->imr.imr_interface.s_addr = inet_addr(ch->intface);
00356           }
00357           
00358           if(setsockopt(ch->rx_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00359                         (char *)&ch->imr, sizeof(ch->imr)) < 0) {
00360             printf("setsockopt (IP_ADD_MEMBERSHIP) failed: %d\n", error_socket());
00361             fflush(stdout);
00362                 close_socket(ch->rx_sock);
00363             return -1;
00364           }
00365         }
00366 #else
00367         ch->imr.imr_multiaddr.s_addr = ch->remote.sin_addr.s_addr;
00368         
00369         if(ch->intface == NULL) {
00370           ch->imr.imr_interface.s_addr = htonl(INADDR_ANY);
00371         }
00372         else {
00373           ch->imr.imr_interface.s_addr = inet_addr(ch->intface);
00374         }
00375         
00376         if(setsockopt(ch->rx_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00377                       (char *)&ch->imr, sizeof(ch->imr)) < 0) {
00378           printf("setsockopt (IP_ADD_MEMBERSHIP) failed: %d\n", error_socket());
00379           fflush(stdout);
00380           close_socket(ch->rx_sock);
00381           return -1;
00382         }
00383 #endif
00384       }
00385       else if(ch->s->addr_family == PF_INET6) {
00386         
00387 #if defined(LINUX) && defined(SSM)
00388         if(ch->s->ssm) {
00389           
00390           if(ch->intface_name == NULL) {
00391             ch->greqs.gsr_interface = 0;
00392           }
00393           else {
00394             ch->greqs.gsr_interface = if_nametoindex(ch->intface_name);
00395           }
00396           
00397           memcpy(&ch->greqs.gsr_group, &ch->remote6, sizeof(ch->remote6));
00398           source.sin6_family = AF_INET6;        
00399           
00400           inet_pton(AF_INET6, ch->s->src_addr, &source.sin6_addr);
00401           memcpy(&ch->greqs.gsr_source, &source, sizeof(source));
00402           
00403           if(setsockopt(ch->rx_sock, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP,
00404                         (char *)&ch->greqs, sizeof(ch->greqs)) < 0) {
00405             
00406             printf("setsockopt (MCAST_JOIN_SOURCE_GROUP) failed: %d\n", error_socket());
00407             fflush(stdout);
00408             close_socket(ch->rx_sock);
00409             return -1;
00410           }
00411         }
00412         else {
00413           ch->imr6.ipv6mr_multiaddr = ch->remote6.sin6_addr;
00414           
00415           if(ch->intface_name == NULL) {
00416             ch->imr6.ipv6mr_interface = 0;
00417           }
00418           else {
00419             ch->imr6.ipv6mr_interface = if_nametoindex(ch->intface_name);
00420           }
00421           
00422           if(setsockopt(ch->rx_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
00423                         (char *)&ch->imr6, sizeof(ch->imr6)) < 0) {
00424             
00425             printf("setsockopt (IPV6_JOIN_GROUP) failed: %d\n", error_socket());
00426             fflush(stdout);
00427             close_socket(ch->rx_sock);
00428             return -1;
00429           }
00430         }
00431 #else
00432         ch->imr6.ipv6mr_multiaddr = ch->remote6.sin6_addr;
00433         
00434 #ifdef LINUX
00435         if(ch->intface_name == NULL) {
00436           ch->imr6.ipv6mr_interface = 0;
00437         }
00438         else {
00439           ch->imr6.ipv6mr_interface = if_nametoindex(ch->intface_name);
00440         }
00441 #else
00442         if(ch->intface_name == NULL) {
00443           ch->imr6.ipv6mr_interface = 0;
00444         }
00445         else {
00446           ch->imr6.ipv6mr_interface = atoi(ch->intface_name);
00447         }
00448         
00449 #endif  
00450         if(setsockopt(ch->rx_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
00451                       (char *)&ch->imr6, sizeof(ch->imr6)) < 0) {
00452           printf("setsockopt (IPV6_JOIN_GROUP) failed: %d\n", error_socket());
00453           fflush(stdout);
00454           close_socket(ch->rx_sock);
00455           return -1;
00456         }
00457 #endif
00458       }
00459     }
00460   }
00461   
00462   return 0;
00463 }
00464 
00465 int close_alc_socket(alc_channel_t *ch) {
00466   
00467   int mode;
00468   int addr_type;
00469   mode = ch->s->mode;
00470   addr_type = ch->s->addr_type;
00471   
00472   if(mode == SENDER) {
00473     close_socket(ch->tx_sock);    
00474   }
00475   
00476   if(mode == RECEIVER) {
00477     
00478     if(addr_type == 0) {
00479       
00480       if(ch->s->addr_family == PF_INET) {
00481         
00482 #ifdef SSM
00483         if(ch->s->ssm) {
00484           
00485           if(setsockopt(ch->rx_sock, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP,
00486                         (char *)&ch->source_imr, sizeof(ch->source_imr)) < 0) {
00487             printf("setsockopt (IP_DROP_SOURCE_MEMBERSHIP) failed: %d\n", error_socket());
00488             fflush(stdout);
00489                 close_socket(ch->rx_sock);
00490             return -1;
00491           }
00492         }
00493         else {
00494           if(setsockopt(ch->rx_sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00495                         (char *)&ch->imr, sizeof(ch->imr)) < 0) {
00496             printf("setsockopt (IP_DROP_MEMBERSHIP) failed: %d\n", error_socket());
00497             fflush(stdout);
00498                 close_socket(ch->rx_sock);
00499             return -1;
00500           }
00501         }
00502 #else
00503         if(setsockopt(ch->rx_sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00504                       (char *)&ch->imr, sizeof(ch->imr)) < 0) {
00505           printf("setsockopt (IP_DROP_MEMBERSHIP) failed: %d\n", error_socket());
00506           fflush(stdout);
00507           close_socket(ch->rx_sock);
00508           return -1;
00509         }
00510 #endif
00511       }
00512       else if(ch->s->addr_family == PF_INET6) {
00513         
00514 #if defined(LINUX) && defined(SSM)
00515         if(ch->s->ssm) {
00516           if(setsockopt(ch->rx_sock, IPPROTO_IPV6, MCAST_LEAVE_SOURCE_GROUP,
00517                         (char *)&ch->greqs, sizeof(ch->greqs)) < 0) {
00518             
00519             printf("setsockopt (MCAST_LEAVE_SOURCE_GROUP) failed: %d\n", error_socket());
00520             fflush(stdout);
00521             close(ch->rx_sock);
00522             return -1;
00523           }
00524         }
00525         else {
00526           if(setsockopt(ch->rx_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
00527                         (char *)&ch->imr6, sizeof(ch->imr6)) < 0) {
00528             
00529             printf("setsockopt (IPV6_LEAVE_GROUP) failed: %d\n", error_socket());
00530             fflush(stdout);
00531             close(ch->rx_sock);
00532             return -1;
00533           }
00534         }
00535 #else
00536         if(setsockopt(ch->rx_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
00537                       (char *)&ch->imr6, sizeof(ch->imr6)) < 0) {
00538           printf("setsockopt (IPV6_LEAVE_GROUP) failed: %d\n", error_socket());
00539           fflush(stdout);
00540           close_socket(ch->rx_sock); 
00541           return -1;
00542         }
00543 #endif
00544       }
00545     }
00546 
00547     close_socket(ch->rx_sock);
00548   }
00549   
00550   return 0;
00551 }
00552 

Generated on Fri Mar 9 20:08:50 2007 for MAD-FCL by  doxygen 1.5.0