1. Ruslan Osmanov
  2. pecl-event

Source

pecl-event / classes / event_util.c

Diff from to

File classes/event_util.c

 }
 /* }}} */
 
+/* {{{ proto bool EventUtil::setSocketOption(mixed socket, int level, int optname, int|array optval)
+   Sets socket options for the socket */
+PHP_METHOD(EventUtil, setSocketOption)
+{
+	zval            **ppzfd    , **zoptval;
+	struct linger     lv;
+	int               ov;
+	int               optlen;
+	int               retval;
+	struct timeval    tv;
+	long              level;
+	long              optname;
+	void             *opt_ptr;
+	HashTable        *opt_ht;
+	zval            **l_onoff  , **l_linger;
+	zval            **sec      , **usec;
+	evutil_socket_t   fd;
+	
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZllZ",
+				&ppzfd, &level, &optname, &zoptval) == FAILURE) {
+		return;
+	}
+
+	fd = php_event_zval_to_fd(ppzfd TSRMLS_CC);
+	if (fd == -1) {
+		RETURN_FALSE;
+	}
+
+	errno = 0;
+
+	switch (optname) {
+		case SO_LINGER: {
+			const char l_onoff_key[]  = "l_onoff";
+			const char l_linger_key[] = "l_linger";
+
+			convert_to_array_ex(zoptval);
+			opt_ht = HASH_OF(*zoptval);
+
+			if (zend_hash_find(opt_ht, l_onoff_key, sizeof(l_onoff_key), (void **) &l_onoff) == FAILURE) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_onoff_key);
+				RETURN_FALSE;
+			}
+			if (zend_hash_find(opt_ht, l_linger_key, sizeof(l_linger_key), (void **) &l_linger) == FAILURE) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_linger_key);
+				RETURN_FALSE;
+			}
+
+			convert_to_long_ex(l_onoff);
+			convert_to_long_ex(l_linger);
+
+			lv.l_onoff  = (unsigned short) Z_LVAL_PP(l_onoff);
+			lv.l_linger = (unsigned short) Z_LVAL_PP(l_linger);
+
+			optlen = sizeof(lv);
+			opt_ptr = &lv;
+			break;
+		}
+
+		case SO_RCVTIMEO:
+		case SO_SNDTIMEO: {
+			const char sec_key[]  = "sec";
+			const char usec_key[] = "usec";
+
+			convert_to_array_ex(zoptval);
+			opt_ht = HASH_OF(*zoptval);
+
+			if (zend_hash_find(opt_ht, sec_key, sizeof(sec_key), (void **) &sec) == FAILURE) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", sec_key);
+				RETURN_FALSE;
+			}
+			if (zend_hash_find(opt_ht, usec_key, sizeof(usec_key), (void **) &usec) == FAILURE) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", usec_key);
+				RETURN_FALSE;
+			}
+
+			convert_to_long_ex(sec);
+			convert_to_long_ex(usec);
+
+			tv.tv_sec  = Z_LVAL_PP(sec);
+			tv.tv_usec = Z_LVAL_PP(usec);
+
+			optlen  = sizeof(tv);
+			opt_ptr = &tv;
+			break;
+		}
+		
+		default:
+			convert_to_long_ex(zoptval);
+			ov = Z_LVAL_PP(zoptval);
+
+			optlen = sizeof(ov);
+			opt_ptr = &ov;
+			break;
+	}
+
+	retval = setsockopt(fd, level, optname, opt_ptr, optlen);
+	if (retval != 0) {
+		if (retval != -2) { /* error, but message already emitted */
+			php_error_docref(NULL TSRMLS_CC, E_WARNING,
+					"Unable to set socket option, errno: %d", errno);
+		}
+
+		RETURN_FALSE;
+	}
+
+	RETVAL_TRUE;
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4