--- php-5.1.4/ext/sockets/sockets.c 2006-04-07 16:04:36.000000000 +0200 +++ php-5.1.4-mc/ext/sockets/sockets.c 2006-06-16 19:22:05.000000000 +0200 @@ -16,6 +16,7 @@ | Sterling Hughes | | Jason Greene | | WinSock: Daniel Beulshausen | + | MCAST: Daniel Rozsnyo | +----------------------------------------------------------------------+ */ @@ -482,6 +483,14 @@ REGISTER_LONG_CONSTANT("PHP_NORMAL_READ", PHP_NORMAL_READ, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_BINARY_READ", PHP_BINARY_READ, CONST_CS | CONST_PERSISTENT); + /* Multicast */ + REGISTER_LONG_CONSTANT("IPPROTO_IP", IPPROTO_IP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IP_MULTICAST_TTL", IP_MULTICAST_TTL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IP_MULTICAST_IF", IP_MULTICAST_IF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP, CONST_CS | CONST_PERSISTENT); + #ifndef WIN32 # include "unix_socket_constants.h" #else @@ -1524,6 +1533,9 @@ socklen_t optlen; php_socket *php_sock; int other_val; + u_char other_val_u_char; + struct in_addr other_val_in_addr; + char* other_val_string; long level, optname; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &arg1, &level, &optname) == FAILURE) @@ -1573,6 +1585,31 @@ add_assoc_long(return_value, "usec", tv.tv_usec); break; + + /* Multicast */ + case IP_MULTICAST_LOOP: + case IP_MULTICAST_TTL: + optlen = sizeof(other_val_u_char); + + if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&other_val_u_char, &optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno); + RETURN_FALSE; + } + + RETURN_LONG(other_val_u_char); + + case IP_MULTICAST_IF: + optlen = sizeof(other_val_in_addr); + + if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&other_val_in_addr, &optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno); + RETURN_FALSE; + } + + other_val_string = inet_ntoa(other_val_in_addr); + + RETURN_STRING(other_val_string,1); + default: optlen = sizeof(other_val); @@ -1587,7 +1624,7 @@ } /* }}} */ -/* {{{ proto bool socket_set_option(resource socket, int level, int optname, int|array optval) +/* {{{ proto bool socket_set_option(resource socket, int level, int optname, int|string|array optval) Sets socket options for the socket */ PHP_FUNCTION(socket_set_option) { @@ -1595,7 +1632,10 @@ struct linger lv; struct timeval tv; php_socket *php_sock; - int ov, optlen, retval; + int ov, optlen, retval; + u_char ov_u_char; + struct in_addr ov_in_addr; + struct ip_mreq ov_ip_mreq; #ifdef PHP_WIN32 int timeout; #endif @@ -1605,12 +1645,15 @@ HashTable *opt_ht; zval **l_onoff, **l_linger; zval **sec, **usec; + zval **multiaddr, **interface; /* key name constants */ char *l_onoff_key = "l_onoff"; char *l_linger_key = "l_linger"; char *sec_key = "sec"; char *usec_key = "usec"; + char *multiaddr_key = "multiaddr"; + char *interface_key = "interface"; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllz", &arg1, &level, &optname, &arg4) == FAILURE) return; @@ -1669,6 +1712,67 @@ opt_ptr = &timeout; #endif break; + + /* Multicast */ + case IP_MULTICAST_LOOP: + convert_to_long_ex(&arg4); + ov_u_char = Z_LVAL_P(arg4) != 0; + + optlen = sizeof(ov_u_char); + opt_ptr = &ov_u_char; + break; + case IP_MULTICAST_TTL: + convert_to_long_ex(&arg4); + ov = Z_LVAL_P(arg4); + if (ov<0) ov=0; + if (ov>255) ov=255; + ov_u_char = ov & 0xFF; + + optlen = sizeof(ov_u_char); + opt_ptr = &ov_u_char; + break; + case IP_MULTICAST_IF: + convert_to_string_ex(&arg4); + if (!inet_aton(Z_STRVAL_PP(&arg4), &ov_in_addr)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert optval to inet_addr" ); + RETURN_FALSE; + } + + optlen = sizeof(ov_in_addr); + opt_ptr = &ov_in_addr; + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + convert_to_array_ex(&arg4); + opt_ht = HASH_OF(arg4); + + if (zend_hash_find(opt_ht, multiaddr_key, strlen(multiaddr_key) + 1, (void **)&multiaddr) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", multiaddr_key); + RETURN_FALSE; + } + + convert_to_string_ex(multiaddr); + + if (!inet_aton(Z_STRVAL_PP(multiaddr), &(ov_ip_mreq.imr_multiaddr))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert optval[multiaddr] to inet_addr" ); + RETURN_FALSE; + } + + if (zend_hash_find(opt_ht, interface_key, strlen(interface_key) + 1, (void **)&interface) == FAILURE) { + ov_ip_mreq.imr_interface.s_addr = htonl(INADDR_ANY); + } else { + convert_to_string_ex(interface); + + if (!inet_aton(Z_STRVAL_PP(interface), &(ov_ip_mreq.imr_interface))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert optval[interface] to inet_addr" ); + RETURN_FALSE; + } + } + + optlen = sizeof(ov_ip_mreq); + opt_ptr = &ov_ip_mreq; + break; + default: convert_to_long_ex(&arg4); ov = Z_LVAL_P(arg4);