Example #1
0
File: db.cpp Project: 191919/hhvm
PHP_METHOD(MongoDB, execute)
{
	zval *code = NULL, *args = NULL, *options = NULL, *zdata;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|aa", &code, &args, &options) == FAILURE) {
		return;
	}

	/* turn the first argument into MongoCode */
	if (Z_TYPE_P(code) != IS_OBJECT ||
		Z_OBJCE_P(code) != mongo_ce_Code) {
		if (Z_TYPE_P(code) == IS_STRING) {
			zval *obj;

			MAKE_STD_ZVAL(obj);
			object_init_ex(obj, mongo_ce_Code);
			MONGO_METHOD1(MongoCode, __construct, return_value, obj, code);
			code = obj;
		} else { /* This is broken code */
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "The argument is neither an object of MongoCode or a string");
			return;
		}
	} else {
		zval_add_ref(&code);
	}

	if (!args) {
		MAKE_STD_ZVAL(args);
		array_init(args);
	} else {
		zval_add_ref(&args);
	}

	/* create { $eval : code, args : [] } */
	MAKE_STD_ZVAL(zdata);
	array_init(zdata);
	add_assoc_zval(zdata, "$eval", code);
	add_assoc_zval(zdata, "args", args);
	/* Check whether we have nolock as an option */
	if (options) {
		zval **nolock;

		if (zend_hash_find(HASH_P(options), "nolock", strlen("nolock") + 1, (void**) &nolock) == SUCCESS) {
			convert_to_boolean_ex(nolock);
			zval_add_ref(nolock);
			add_assoc_zval(zdata, "nolock", *nolock);
		}
	}

	MONGO_METHOD1(MongoDB, command, return_value, getThis(), zdata);

	zval_ptr_dtor(&zdata);
}
Example #2
0
bool samphp::callBool(char *fn, char *argspec, ...)
{
    bool rrv = false;

    zval *rv;

    va_list ap;
    va_start(ap, argspec);
    rv = call(fn, argspec, ap TSRMLS_CC);
    va_end(ap);

    if(rv)
    {
        if(Z_TYPE_P(rv) != IS_BOOL)
        {
            // copy rv into new memory for the in place conversion
            zval *cp;
            MAKE_STD_ZVAL(cp);
            *cp = *rv;
            zval_copy_ctor(cp);
            INIT_PZVAL(cp);

            // destroy the original now that we have a copy
            zval_ptr_dtor(&rv);

            // rename rv to our copy
            rv = cp;
            convert_to_boolean_ex(&rv);
        }

        rrv = (bool)Z_LVAL_P(rv);
        zval_ptr_dtor(&rv);
    }

    return rrv;
}
Example #3
0
/* Returns the bytes read on success
 * Returns -31 on unknown failure
 * Returns -80 on timeout
 * Returns -32 when remote server closes the connection
 */
int php_mongo_io_stream_read(mongo_connection *con, mongo_server_options *options, int timeout, void *data, int size, char **error_message)
{
	int num = 1, received = 0;
	TSRMLS_FETCH();

	int socketTimeoutMS = options->socketTimeoutMS ? options->socketTimeoutMS : FG(default_socket_timeout) * 1000;

	/* Convert negative values to -1 second, which implies no timeout */
	socketTimeoutMS = socketTimeoutMS < 0 ? -1000 : socketTimeoutMS;
	timeout = timeout < 0 ? -1000 : timeout;

	/* Socket timeout behavior varies based on the following:
	 * - Negative => no timeout (i.e. block indefinitely)
	 * - Zero => not specified (no changes to existing configuration)
	 * - Positive => used specified timeout (revert to previous value later) */
	if (timeout && timeout != socketTimeoutMS) {
		struct timeval rtimeout = {0, 0};

		rtimeout.tv_sec = timeout / 1000;
		rtimeout.tv_usec = (timeout % 1000) * 1000;

		php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout);
		mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "Setting the stream timeout to %d.%06d", rtimeout.tv_sec, rtimeout.tv_usec);
	} else {
		mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "No timeout changes for %s", con->hash);
	}

	php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_READ, 0, size TSRMLS_CC);

	/* this can return FAILED if there is just no more data from db */
	while (received < size && num > 0) {
		int len = 4096 < (size - received) ? 4096 : size - received;
		ERROR_HANDLER_DECLARATION(error_handler)

		ERROR_HANDLER_REPLACE(error_handler, mongo_ce_ConnectionException);
		num = php_stream_read(con->socket, (char *) data, len);
		ERROR_HANDLER_RESTORE(error_handler);

		if (num < 0) {
			/* Doesn't look like this can happen, php_sockop_read overwrites
			 * the failure from recv() to return 0 */
			*error_message = strdup("Read from socket failed");
			return -31;
		}

		/* It *may* have failed. It also may simply have no data */
		if (num == 0) {
			zval *metadata;

			MAKE_STD_ZVAL(metadata);
			array_init(metadata);
			if (php_stream_populate_meta_data(con->socket, metadata)) {
				zval **tmp;

				if (zend_hash_find(Z_ARRVAL_P(metadata), "timed_out", sizeof("timed_out"), (void**)&tmp) == SUCCESS) {
					convert_to_boolean_ex(tmp);
					if (Z_BVAL_PP(tmp)) {
						struct timeval rtimeout = {0, 0};

						if (timeout > 0 && options->socketTimeoutMS != timeout) {
							rtimeout.tv_sec = timeout / 1000;
							rtimeout.tv_usec = (timeout % 1000) * 1000;
						} else {
							/* Convert timeout=-1 to -1second, which PHP interprets as no timeout */
							int socketTimeoutMS = options->socketTimeoutMS == -1 ? -1000 : options->socketTimeoutMS;
							rtimeout.tv_sec = socketTimeoutMS / 1000;
							rtimeout.tv_usec = (socketTimeoutMS % 1000) * 1000;
						}
						*error_message = malloc(256);
						snprintf(*error_message, 256, "Read timed out after reading %d bytes, waited for %d.%06d seconds", num, rtimeout.tv_sec, rtimeout.tv_usec);
						zval_ptr_dtor(&metadata);
						return -80;
					}
				}
				if (zend_hash_find(Z_ARRVAL_P(metadata), "eof", sizeof("eof"), (void**)&tmp) == SUCCESS) {
					convert_to_boolean_ex(tmp);
					if (Z_BVAL_PP(tmp)) {
						*error_message = strdup("Remote server has closed the connection");
						zval_ptr_dtor(&metadata);
						return -32;
					}
				}
			}
			zval_ptr_dtor(&metadata);
		}

		data = (char*)data + num;
		received += num;
	}
	/* PHP may have sent notify-progress of *more then* 'received' in some
	 * cases.
	 * PHP will read 8192 byte chunks at a time, but if we request less data
	 * then that PHP will just buffer the rest, which is fine.  It could
	 * confuse users a little, why their progress update was higher then the
	 * max-bytes-expected though... */
	php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_COMPLETED, received, size TSRMLS_CC);

	/* If the timeout was changed, revert to the previous value now */
	if (timeout && timeout != socketTimeoutMS) {
		struct timeval rtimeout = {0, 0};

		/* If socketTimeoutMS was never specified, revert to default_socket_timeout */
		if (options->socketTimeoutMS == 0) {
			mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "Stream timeout will be reverted to default_socket_timeout (%d)", FG(default_socket_timeout));
		}

		rtimeout.tv_sec = socketTimeoutMS / 1000;
		rtimeout.tv_usec = (socketTimeoutMS % 1000) * 1000;

		php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout);
		mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "Now setting stream timeout back to %d.%06d", rtimeout.tv_sec, rtimeout.tv_usec);
	}

	return received;
}
Example #4
0
/* Returns the bytes read on success
 * Returns -31 on unknown failure
 * Returns -80 on timeout
 * Returns -32 when remote server closes the connection
 */
int php_mongo_io_stream_read(mongo_connection *con, mongo_server_options *options, int timeout, void *data, int size, char **error_message)
{
	int num = 1, received = 0;
	TSRMLS_FETCH();

	if (timeout > 0 && options->socketTimeoutMS != timeout) {
		struct timeval rtimeout = {0, 0};
		rtimeout.tv_sec = timeout / 1000;
		rtimeout.tv_usec = (timeout % 1000) * 1000;

		php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout);
	}

	php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_READ, 0, size TSRMLS_CC);

	/* this can return FAILED if there is just no more data from db */
	while (received < size && num > 0) {
		int len = 4096 < (size - received) ? 4096 : size - received;
		ERROR_HANDLER_DECLARATION(error_handler)

		ERROR_HANDLER_REPLACE(error_handler, mongo_ce_ConnectionException);
		num = php_stream_read(con->socket, (char *) data, len);
		ERROR_HANDLER_RESTORE(error_handler);

		if (num < 0) {
			/* Doesn't look like this can happen, php_sockop_read overwrites
			 * the failure from recv() to return 0 */
			*error_message = strdup("Read from socket failed");
			return -31;
		}

		/* It *may* have failed. It also may simply have no data */
		if (num == 0) {
			zval *metadata;

			MAKE_STD_ZVAL(metadata);
			array_init(metadata);
			if (php_stream_populate_meta_data(con->socket, metadata)) {
				zval **tmp;

				if (zend_hash_find(Z_ARRVAL_P(metadata), "timed_out", sizeof("timed_out"), (void**)&tmp) == SUCCESS) {
					convert_to_boolean_ex(tmp);
					if (Z_BVAL_PP(tmp)) {
						struct timeval rtimeout = {0, 0};

						if (timeout > 0 && options->socketTimeoutMS != timeout) {
							rtimeout.tv_sec = timeout / 1000;
							rtimeout.tv_usec = (timeout % 1000) * 1000;
						} else {
							rtimeout.tv_sec = options->socketTimeoutMS / 1000;
							rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000;
						}
						*error_message = malloc(256);
						snprintf(*error_message, 256, "Read timed out after reading %d bytes, waited for %d.%06d seconds", num, rtimeout.tv_sec, rtimeout.tv_usec);
						zval_ptr_dtor(&metadata);
						return -80;
					}
				}
				if (zend_hash_find(Z_ARRVAL_P(metadata), "eof", sizeof("eof"), (void**)&tmp) == SUCCESS) {
					convert_to_boolean_ex(tmp);
					if (Z_BVAL_PP(tmp)) {
						*error_message = strdup("Remote server has closed the connection");
						zval_ptr_dtor(&metadata);
						return -32;
					}
				}
			}
			zval_ptr_dtor(&metadata);
		}

		data = (char*)data + num;
		received += num;
	}
	/* PHP may have sent notify-progress of *more then* 'received' in some
	 * cases.
	 * PHP will read 8192 byte chunks at a time, but if we request less data
	 * then that PHP will just buffer the rest, which is fine.  It could
	 * confuse users a little, why their progress update was higher then the
	 * max-bytes-expected though... */
	php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_COMPLETED, received, size TSRMLS_CC);

	if (timeout > 0 && options->socketTimeoutMS != timeout) {
		struct timeval rtimeout = {0, 0};
		rtimeout.tv_sec = options->socketTimeoutMS / 1000;
		rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000;

		php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout);
	}

	return received;
}
void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval** value, HashTable* fieldspec) {
  // At this point the typeID (and field num, if applicable) should've already been written to the output so all we need to do is write the payload.
  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      return;
    case T_STRUCT: {
      TSRMLS_FETCH();
      zval* spec = zend_read_static_property(zend_get_class_entry(*value TSRMLS_CC), "_TSPEC", 6, false TSRMLS_CC);
      binary_serialize_spec(*value, transport, Z_ARRVAL_P(spec));
    } return;
    case T_BOOL:
      convert_to_boolean_ex(value);
      transport.writeI8(Z_BVAL_PP(value) ? 1 : 0);
      return;
    case T_BYTE:
      convert_to_long_ex(value);
      transport.writeI8(Z_LVAL_PP(value));
      return;
    case T_I16:
      convert_to_long_ex(value);
      transport.writeI16(Z_LVAL_PP(value));
      return;
    case T_I32:
      convert_to_long_ex(value);
      transport.writeI32(Z_LVAL_PP(value));
      return;
    case T_I64:
    case T_U64:
      convert_to_long_ex(value);
      transport.writeI64(Z_LVAL_PP(value));
      return;
    case T_DOUBLE: {
      union {
        int64_t c;
        double d;
      } a;
      convert_to_double_ex(value);
      a.d = Z_DVAL_PP(value);
      transport.writeI64(a.c);
    } return;
    //case T_UTF7:
    case T_UTF8:
    case T_UTF16:
    case T_STRING:
      convert_to_string(*value);
      transport.writeString(Z_STRVAL_PP(value), Z_STRLEN_PP(value));
      return;
    case T_MAP: {
      HashTable* ht = Z_ARRVAL_PP(value);
      zval** val_ptr;

      zend_hash_find(fieldspec, "ktype", 6, (void**)&val_ptr);
      convert_to_long_ex(val_ptr);
      uint8_t keytype = Z_LVAL_PP(val_ptr);
      transport.writeI8(keytype);
      zend_hash_find(fieldspec, "vtype", 6, (void**)&val_ptr);
      convert_to_long_ex(val_ptr);
      uint8_t valtype = Z_LVAL_PP(val_ptr);
      transport.writeI8(valtype);

      zend_hash_find(fieldspec, "val", 4, (void**)&val_ptr);
      HashTable* valspec = Z_ARRVAL_PP(val_ptr);

      transport.writeI32(zend_hash_num_elements(ht));
      HashPosition key_ptr;
      for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) {
        binary_serialize_hashtable_key(keytype, transport, ht, key_ptr);
        binary_serialize(valtype, transport, val_ptr, valspec);
      }
    } return;
    case T_LIST: {
      HashTable* ht = Z_ARRVAL_PP(value);
      zval** val_ptr;

      zend_hash_find(fieldspec, "etype", 6, (void**)&val_ptr);
      convert_to_long_ex(val_ptr);
      uint8_t valtype = Z_LVAL_PP(val_ptr);
      transport.writeI8(valtype);

      zend_hash_find(fieldspec, "elem", 5, (void**)&val_ptr);
      HashTable* valspec = Z_ARRVAL_PP(val_ptr);

      transport.writeI32(zend_hash_num_elements(ht));
      HashPosition key_ptr;
      for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) {
        binary_serialize(valtype, transport, val_ptr, valspec);
      }
    } return;
    case T_SET: {
      HashTable* ht = Z_ARRVAL_PP(value);
      zval** val_ptr;

      zend_hash_find(fieldspec, "etype", 6, (void**)&val_ptr);
      convert_to_long_ex(val_ptr);
      uint8_t keytype = Z_LVAL_PP(val_ptr);
      transport.writeI8(keytype);

      transport.writeI32(zend_hash_num_elements(ht));
      HashPosition key_ptr;
      for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) {
        binary_serialize_hashtable_key(keytype, transport, ht, key_ptr);
      }
    } return;
  };
  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(errbuf, INVALID_DATA);
}
Example #6
0
/* Returns the bytes read on success
 * Returns -31 on unknown failure
 * Returns -80 on timeout
 * Returns -32 when remote server closes the connection
 */
int php_mongo_io_stream_read(mongo_connection *con, mongo_server_options *options, int timeout, void *data, int size, char **error_message)
{
	int num = 1, received = 0;
	TSRMLS_FETCH();

	if (timeout > 0 && options->socketTimeoutMS != timeout) {
		struct timeval rtimeout = {0};
		rtimeout.tv_sec = timeout / 1000;
		rtimeout.tv_usec = (timeout % 1000) * 1000;

		php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout);
	}

	/* this can return FAILED if there is just no more data from db */
	while (received < size && num > 0) {
		int len = 4096 < (size - received) ? 4096 : size - received;

		num = php_stream_read(con->socket, (char *) data, len);

		if (num < 0) {
			/* Doesn't look like this can happen, php_sockop_read overwrites
			 * the failure from recv() to return 0 */
			*error_message = strdup("Read from socket failed");
			return -31;
		}

		/* It *may* have failed. It also may simply have no data */
		if (num == 0) {
			zval *metadata;

			MAKE_STD_ZVAL(metadata);
			array_init(metadata);
			if (php_stream_populate_meta_data(con->socket, metadata)) {
				zval **tmp;

				if (zend_hash_find(Z_ARRVAL_P(metadata), "timed_out", sizeof("timed_out"), (void**)&tmp) == SUCCESS) {
					convert_to_boolean_ex(tmp);
					if (Z_BVAL_PP(tmp)) {
						struct timeval rtimeout = {0};

						if (timeout > 0 && options->socketTimeoutMS != timeout) {
							rtimeout.tv_sec = timeout / 1000;
							rtimeout.tv_usec = (timeout % 1000) * 1000;
						} else {
							rtimeout.tv_sec = options->socketTimeoutMS / 1000;
							rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000;
						}
						*error_message = malloc(256);
						snprintf(*error_message, 256, "Read timed out after reading %d bytes, waited for %d.%06d seconds", num, rtimeout.tv_sec, rtimeout.tv_usec);
						zval_ptr_dtor(&metadata);
						return -80;
					}
				}
				if (zend_hash_find(Z_ARRVAL_P(metadata), "eof", sizeof("eof"), (void**)&tmp) == SUCCESS) {
					convert_to_boolean_ex(tmp);
					if (Z_BVAL_PP(tmp)) {
						*error_message = strdup("Remote server has closed the connection");
						zval_ptr_dtor(&metadata);
						return -32;
					}
				}
			}
			zval_ptr_dtor(&metadata);
		}

		data = (char*)data + num;
		received += num;
	}

	if (options && options->ctx) {
		php_stream_notify_progress_increment((php_stream_context *)options->ctx, received, size);
	}
	if (timeout > 0 && options->socketTimeoutMS != timeout) {
		struct timeval rtimeout = {0};
		rtimeout.tv_sec = options->socketTimeoutMS / 1000;
		rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000;

		php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout);
	}

	return received;
}
Example #7
0
int php_do_setsockopt_ipv6_mcast(php_socket *php_sock,
								 int level,
								 int optname,
								 zval *arg4)
{
	unsigned int	if_index;
	void			*opt_ptr;
	socklen_t		optlen;
	int				ov;
	int				retval;

	switch (optname) {
	case PHP_MCAST_JOIN_GROUP:
	case PHP_MCAST_LEAVE_GROUP:
#ifdef HAS_MCAST_EXT
	case PHP_MCAST_BLOCK_SOURCE:
	case PHP_MCAST_UNBLOCK_SOURCE:
	case PHP_MCAST_JOIN_SOURCE_GROUP:
	case PHP_MCAST_LEAVE_SOURCE_GROUP:
#endif
		if (php_do_mcast_opt(php_sock, level, optname, arg4) == FAILURE) {
			return FAILURE;
		} else {
			return SUCCESS;
		}

	case IPV6_MULTICAST_IF:
		if (php_get_if_index_from_zval(arg4, &if_index) == FAILURE) {
			return FAILURE;
		}

		opt_ptr = &if_index;
		optlen	= sizeof(if_index);
		goto dosockopt;

	case IPV6_MULTICAST_LOOP:
		convert_to_boolean_ex(arg4);
		ov = (int) Z_TYPE_P(arg4) == IS_TRUE;
		goto ipv6_loop_hops;
	case IPV6_MULTICAST_HOPS:
		convert_to_long_ex(arg4);
		if (Z_LVAL_P(arg4) < -1L || Z_LVAL_P(arg4) > 255L) {
			php_error_docref(NULL, E_WARNING,
					"Expected a value between -1 and 255");
			return FAILURE;
		}
		ov = (int) Z_LVAL_P(arg4);
ipv6_loop_hops:
		opt_ptr = &ov;
		optlen	= sizeof(ov);
		goto dosockopt;
	}

	return 1; /* not handled */

dosockopt:
	retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen);
	if (retval != 0) {
		PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
		return FAILURE;
	}

	return SUCCESS;
}
Example #8
0
int php_do_setsockopt_ip_mcast(php_socket *php_sock,
							   int level,
							   int optname,
							   zval *arg4)
{
	unsigned int	if_index;
	struct in_addr	if_addr;
	void 			*opt_ptr;
	socklen_t		optlen;
	unsigned char	ipv4_mcast_ttl_lback;
	int				retval;

	switch (optname) {
	case PHP_MCAST_JOIN_GROUP:
	case PHP_MCAST_LEAVE_GROUP:
#ifdef HAS_MCAST_EXT
	case PHP_MCAST_BLOCK_SOURCE:
	case PHP_MCAST_UNBLOCK_SOURCE:
	case PHP_MCAST_JOIN_SOURCE_GROUP:
	case PHP_MCAST_LEAVE_SOURCE_GROUP:
#endif
		if (php_do_mcast_opt(php_sock, level, optname, arg4) == FAILURE) {
			return FAILURE;
		} else {
			return SUCCESS;
		}

	case IP_MULTICAST_IF:
		if (php_get_if_index_from_zval(arg4, &if_index) == FAILURE) {
			return FAILURE;
		}

		if (php_if_index_to_addr4(if_index, php_sock, &if_addr) == FAILURE) {
			return FAILURE;
		}
		opt_ptr = &if_addr;
		optlen	= sizeof(if_addr);
		goto dosockopt;

	case IP_MULTICAST_LOOP:
		convert_to_boolean_ex(arg4);
		ipv4_mcast_ttl_lback = (unsigned char) (Z_TYPE_P(arg4) == IS_TRUE);
		goto ipv4_loop_ttl;

	case IP_MULTICAST_TTL:
		convert_to_long_ex(arg4);
		if (Z_LVAL_P(arg4) < 0L || Z_LVAL_P(arg4) > 255L) {
			php_error_docref(NULL, E_WARNING,
					"Expected a value between 0 and 255");
			return FAILURE;
		}
		ipv4_mcast_ttl_lback = (unsigned char) Z_LVAL_P(arg4);
ipv4_loop_ttl:
		opt_ptr = &ipv4_mcast_ttl_lback;
		optlen	= sizeof(ipv4_mcast_ttl_lback);
		goto dosockopt;
	}

	return 1;

dosockopt:
	retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen);
	if (retval != 0) {
		PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
		return FAILURE;
	}

	return SUCCESS;
}
Example #9
0
// PHP函数参数转换为go类型的参数
static void* phpgo_function_conv_arg(int cbid, int idx, char ch, int zty, zval **zarg)
{
    int prmty = zty;
    void *rv = NULL;

    if (ch == 's') {
        if (prmty != IS_STRING) {
            zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s",
                       ch, type2name(prmty));
        }

        convert_to_string_ex(zarg);
        char *arg = Z_STRVAL_PP(zarg);
        printf("arg%d(%c), %s(%d)\n", idx, ch, arg, Z_STRLEN_PP(zarg));
        goapi_new_value(GT_String, (uint64_t)arg, &rv);
    } else if (ch == 'l') {
        if (prmty != IS_LONG) {
            zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s",
                       ch, type2name(prmty));
        }

        convert_to_long_ex(zarg);
        long arg = (long)Z_LVAL_PP(zarg);
        printf("arg%d(%c), %d\n", idx, ch, arg);
        goapi_new_value(GT_Int64, (uint64_t)arg, &rv);
    } else if (ch == 'b') {
        convert_to_boolean_ex(zarg);
        zend_bool arg = (zend_bool)Z_BVAL_PP(zarg);
        goapi_new_value(GT_Bool, (uint64_t)arg, &rv);
    } else if (ch == 'd') {
        convert_to_double_ex(zarg);
        double arg = (double)Z_DVAL_PP(zarg);
        double* parg = calloc(1, sizeof(double));
        *parg = (double)Z_DVAL_PP(zarg);
        // argv[idx] = (void*)(ulong)arg;  // error
        // memcpy(&argv[idx], &arg, sizeof(argv[idx])); // ok
        // float32(uintptr(ax))
        goapi_new_value(GT_Float64, (uint64_t)parg, &rv);
    } else if (ch == 'a') {
        if (Z_TYPE_PP(zarg) == IS_STRING) {
            char *arg = Z_STRVAL_PP(zarg);
            goapi_new_value(GT_String, (uint64_t)arg, &rv);
#ifdef ZEND_ENGINE_3
        } else if (Z_TYPE_PP(zarg) == _IS_BOOL) {
#else
        } else if (Z_TYPE_PP(zarg) == IS_BOOL) {
#endif
            zend_bool arg = (zend_bool)Z_BVAL_PP(zarg);
            goapi_new_value(GT_Bool, (uint64_t)arg, &rv);
        } else if (Z_TYPE_PP(zarg) == IS_DOUBLE) {
            double* parg = calloc(1, sizeof(double));
            *parg = (double)Z_DVAL_PP(zarg);
            goapi_new_value(GT_Float64, (uint64_t)parg, &rv);
        } else if (Z_TYPE_PP(zarg) == IS_LONG) {
            long arg = (long)Z_LVAL_PP(zarg);
            goapi_new_value(GT_Int64, (uint64_t)arg, &rv);
        } else if (Z_TYPE_PP(zarg) == IS_OBJECT) {
            void *parg = (void*)zarg;
            goapi_new_value(GT_UnsafePointer, (uint64_t)parg, &rv);
        } else if (Z_TYPE_PP(zarg) == IS_RESOURCE) {
            void *parg = (void*)zarg;
            goapi_new_value(GT_UnsafePointer, (uint64_t)parg, &rv);
        } else {
            printf("arg%d(%c), %s(%d) unsported to Any\n", idx, ch,
                   type2name(Z_TYPE_PP(zarg)), Z_TYPE_PP(zarg));
        }

        // TODO array/vector convert
    } else if (ch == 'v') {
        HashTable *arr_hash = Z_ARRVAL_PP(zarg);
        HashPosition pos;
        zval **edata;

        for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos);
#ifdef ZEND_ENGINE_3
             (edata = zend_hash_get_current_data_ex(arr_hash, &pos)) != NULL;
#else
             zend_hash_get_current_data_ex(arr_hash, (void**)&edata, &pos) == SUCCESS;
#endif
             zend_hash_move_forward_ex(arr_hash, &pos)) {

            if (rv == NULL) {
                switch (Z_TYPE_PP(edata)) {
                case IS_LONG:
                    goapi_array_new(GT_Int64, &rv);
                    break;
                default:
                    goapi_array_new(GT_String, &rv);
                    break;
                }
            }

            switch (Z_TYPE_PP(edata)) {
            case IS_LONG:
                goapi_array_push(rv, (void*)Z_LVAL_PP(edata), &rv);
                break;
            default:
                convert_to_string_ex(edata);
                printf("array idx(%d)=T(%d=%s, val=%s)\n", pos,
                       Z_TYPE_PP(edata), type2name(Z_TYPE_PP(edata)), Z_STRVAL_PP(edata));
                goapi_array_push(rv, Z_STRVAL_PP(edata), &rv);
                break;
            }
        }

        // TODO array/map convert
    } else if (ch == 'm') {
PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage)
{
      OLECHAR *unicode_str;

      var_arg->vt = (short) pval_type->value.lval;

      switch(var_arg->vt)
      {
         case VT_UI1:
            convert_to_long_ex(&pval_arg);
            var_arg->bVal = (unsigned char)pval_arg->value.lval;
            break;

         case VT_I2:
            convert_to_long_ex(&pval_arg);
            var_arg->iVal = (short)pval_arg->value.lval;
            break;

         case VT_I4:
            convert_to_long_ex(&pval_arg);
            var_arg->lVal = pval_arg->value.lval;
            break;

         case VT_R4:
            convert_to_double_ex(&pval_arg);
            var_arg->fltVal = (float)pval_arg->value.dval;
            break;

         case VT_R8:
            convert_to_double_ex(&pval_arg);
            var_arg->dblVal = pval_arg->value.dval;
            break;

         case VT_BOOL:
            convert_to_boolean_ex(&pval_arg);
            var_arg->boolVal = (short)pval_arg->value.lval;
            break;

         case VT_ERROR:
            convert_to_long_ex(&pval_arg);
            var_arg->scode = pval_arg->value.lval;
            break;

         case VT_CY:
            convert_to_double_ex(&pval_arg);
            VarCyFromR8(pval_arg->value.dval, &(var_arg->cyVal));
            break;

         case VT_DATE:
         {
            SYSTEMTIME wintime;
            struct tm *phptime;

            phptime = gmtime(&(pval_arg->value.lval));

            wintime.wYear = phptime->tm_year + 1900;
            wintime.wMonth = phptime->tm_mon + 1;
            wintime.wDay = phptime->tm_mday;
            wintime.wHour = phptime->tm_hour;
            wintime.wMinute = phptime->tm_min;
            wintime.wSecond = phptime->tm_sec;

            SystemTimeToVariantTime(&wintime, &(var_arg->date));
         }

         case VT_BSTR:
            convert_to_string_ex(&pval_arg);
            unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
            var_arg->bstrVal = SysAllocString(unicode_str);
            efree(unicode_str);
            break;

         case VT_DECIMAL:
            convert_to_string_ex(&pval_arg);
            unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
            VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &(var_arg->decVal));
            break;

         case VT_DECIMAL|VT_BYREF:
            convert_to_string_ex(&pval_arg);
            unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
            VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, var_arg->pdecVal);
            break;

         case VT_UNKNOWN:
            php_pval_to_variant(pval_arg, var_arg, codepage);
            if(var_arg->vt != VT_DISPATCH)
               var_arg->vt = VT_EMPTY;
            else
            {
               HRESULT hr;

               hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal));

               if (FAILED(hr))
               {
                  php_error(E_WARNING,"can't query IUnknown");
                  var_arg->vt = VT_EMPTY;
               }
               else
                  var_arg->vt = VT_UNKNOWN;
            }
            break;

         case VT_DISPATCH:
            php_pval_to_variant(pval_arg, var_arg, codepage);
            if(var_arg->vt != VT_DISPATCH)
               var_arg->vt = VT_EMPTY;
            break;

         case VT_UI1|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->pbVal = (unsigned char FAR*) &(pval_arg->value.lval);
            break;

         case VT_I2|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->piVal = (short FAR*) &(pval_arg->value.lval);
            break;

         case VT_I4|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->plVal = (long FAR*) &(pval_arg->value.lval);
            break;

         case VT_R4|VT_BYREF:
            convert_to_double(pval_arg);
            var_arg->pfltVal = (float FAR*) &(pval_arg->value.lval);
            break;

         case VT_R8|VT_BYREF:
            convert_to_double(pval_arg);
            var_arg->pdblVal = (double FAR*) &(pval_arg->value.lval);
            break;

         case VT_BOOL|VT_BYREF:
            convert_to_boolean(pval_arg);
            var_arg->pboolVal = (short FAR*) &(pval_arg->value.lval);
            break;

         case VT_ERROR|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->pscode = (long FAR*) &(pval_arg->value.lval);
            break;

         case VT_CY|VT_BYREF:
            convert_to_double_ex(&pval_arg);
            VarCyFromR8(pval_arg->value.dval, var_arg->pcyVal);
            break;

         case VT_DATE|VT_BYREF:
         {
            SYSTEMTIME wintime;
            struct tm *phptime;

            phptime = gmtime(&(pval_arg->value.lval));

            wintime.wYear   = phptime->tm_year + 1900;
            wintime.wMonth  = phptime->tm_mon + 1;
            wintime.wDay    = phptime->tm_mday;
            wintime.wHour   = phptime->tm_hour;
            wintime.wMinute = phptime->tm_min;
            wintime.wSecond = phptime->tm_sec;

            SystemTimeToVariantTime(&wintime, var_arg->pdate);
         }

         case VT_BSTR|VT_BYREF:
            convert_to_string(pval_arg);
            var_arg->pbstrVal = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
            unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
            *(var_arg->pbstrVal) = SysAllocString(unicode_str);
            efree(unicode_str);
            break;

         case VT_UNKNOWN|VT_BYREF:
            php_pval_to_variant(pval_arg, var_arg, codepage);
            if(var_arg->vt != VT_DISPATCH)
               var_arg->vt = VT_EMPTY;
            else
            {
               HRESULT hr;

               hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal));

               if (FAILED(hr))
               {
                  php_error(E_WARNING,"can't query IUnknown");
                  var_arg->vt = VT_EMPTY;
               }
               else
                  var_arg->vt = VT_UNKNOWN|VT_BYREF;
            }
            break;

         case VT_DISPATCH|VT_BYREF:
            php_pval_to_variant(pval_arg, var_arg, codepage);
            if(var_arg->vt != VT_DISPATCH)
               var_arg->vt = VT_EMPTY;
            else
               var_arg->vt |= VT_BYREF;
            break;

         case VT_VARIANT|VT_BYREF:
            php_pval_to_variant(pval_arg, var_arg, codepage);
            if(var_arg->vt != (VT_VARIANT | VT_BYREF))
               var_arg->vt = VT_EMPTY;
            break;

         case VT_I1:
            convert_to_long_ex(&pval_arg);
            var_arg->cVal = (char)pval_arg->value.lval;
            break;

         case VT_UI2:
            convert_to_long_ex(&pval_arg);
            var_arg->uiVal = (unsigned short)pval_arg->value.lval;
            break;

         case VT_UI4:
            convert_to_long_ex(&pval_arg);
            var_arg->ulVal = (unsigned long)pval_arg->value.lval;
            break;

         case VT_INT:
            convert_to_long_ex(&pval_arg);
            var_arg->intVal = (int)pval_arg->value.lval;
            break;

         case VT_UINT:
            convert_to_long_ex(&pval_arg);
            var_arg->uintVal = (unsigned int)pval_arg->value.lval;
            break;

         case VT_I1|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->pcVal = (char FAR*) &pval_arg->value.lval;
            break;

         case VT_UI2|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->puiVal = (unsigned short FAR*) &pval_arg->value.lval;
            break;

         case VT_UI4|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->pulVal = (unsigned long FAR*) &pval_arg->value.lval;
            break;

         case VT_INT|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->pintVal = (int FAR*) &pval_arg->value.lval;
            break;

         case VT_UINT|VT_BYREF:
            convert_to_long(pval_arg);
            var_arg->puintVal = (unsigned int FAR*) &pval_arg->value.lval;
            break;

         default:
            php_error(E_WARNING, "Type not supportet or not yet implemented.");
      }
}
Example #11
0
/* {{{ proto object ffmpeg_movie(string filename) 
   Constructor for ffmpeg_movie objects
 */
FFMPEG_PHP_CONSTRUCTOR(ffmpeg_movie, __construct)
{
    int persistent = 0, hashkey_length = 0;
    char *filename = NULL, *fullpath = NULL, *hashkey = NULL;
    zval ***argv;
    ff_movie_context *ffmovie_ctx = NULL;

    /* retrieve arguments */ 
    argv = (zval ***) safe_emalloc(sizeof(zval **), ZEND_NUM_ARGS(), 0);

    if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), argv) != SUCCESS) {
        efree(argv);
        php_error_docref(NULL TSRMLS_CC, E_ERROR,
                "Error parsing arguments");
    }

    switch (ZEND_NUM_ARGS()) {
        case 2:
            convert_to_boolean_ex(argv[1]);

            if (! INI_BOOL("ffmpeg.allow_persistent") && Z_LVAL_PP(argv[1])) {
                zend_error(E_WARNING, 
                        "Persistent movies have been disabled in php.ini");
                break;
            } 

            persistent = Z_LVAL_PP(argv[1]);

            /* fallthru */
        case 1:
            convert_to_string_ex(argv[0]);
            filename = Z_STRVAL_PP(argv[0]);
            break;
        default:
            WRONG_PARAM_COUNT;
    } 

    if (persistent) {
        list_entry *le;
        /* resolve the fully-qualified path name to use as the hash key */
        fullpath = expand_filepath(filename, NULL TSRMLS_CC);

        hashkey_length = sizeof("ffmpeg-php_")-1 + 
            strlen(SAFE_STRING(filename));
        hashkey = (char *) emalloc(hashkey_length+1);
        snprintf(hashkey, hashkey_length, "ffmpeg-php_%s",
			SAFE_STRING(filename));

        
        /* do we have an existing persistent movie? */
        if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, 
                    hashkey_length+1, (void**)&le)) {
            int type;
            
            if (Z_TYPE_P(le) != le_ffmpeg_pmovie) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, 
                        "Failed to retrieve persistent resource");
            }
            ffmovie_ctx = (ff_movie_context*)le->ptr;
           
            /* sanity check to ensure that the resource is still a valid 
             * regular resource number */
            if (zend_list_find(ffmovie_ctx->rsrc_id, &type) == ffmovie_ctx) {
                /* add a reference to the persistent movie */
                zend_list_addref(ffmovie_ctx->rsrc_id);
            } else {
                //php_error_docref(NULL TSRMLS_CC, E_ERROR, 
                //"Not a valid persistent movie resource");
                ffmovie_ctx->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, 
                        ffmovie_ctx, le_ffmpeg_pmovie);
            }
            
        } else { /* no existing persistant movie, create one */
            list_entry new_le;
            ffmovie_ctx = _php_alloc_ffmovie_ctx(1);

            if (_php_open_movie_file(ffmovie_ctx, filename)) {
                zend_error(E_WARNING, "Can't open movie file %s", filename);
                efree(argv);
                ZVAL_BOOL(getThis(), 0);
                RETURN_FALSE;
            }

            Z_TYPE(new_le) = le_ffmpeg_pmovie;
            new_le.ptr = ffmovie_ctx;

            if (FAILURE == zend_hash_update(&EG(persistent_list), hashkey, 
                        hashkey_length+1, (void *)&new_le, sizeof(list_entry),
                        NULL)) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, 
                        "Failed to register persistent resource");
            }
            
            ffmovie_ctx->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ffmovie_ctx, 
                    le_ffmpeg_pmovie);
        }
        
    } else {
        ffmovie_ctx = _php_alloc_ffmovie_ctx(0);
        
        if (_php_open_movie_file(ffmovie_ctx, Z_STRVAL_PP(argv[0]))) {
            zend_error(E_WARNING, "Can't open movie file %s", 
                    Z_STRVAL_PP(argv[0]));
            efree(argv);
            ZVAL_BOOL(getThis(), 0);
            RETURN_FALSE;
        }
        
        /* pass NULL for resource result since we're not returning the resource
           directly, but adding it to the returned object. */
        ffmovie_ctx->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ffmovie_ctx, 
                le_ffmpeg_movie);
    }

    object_init_ex(getThis(), ffmpeg_movie_class_entry_ptr);
    add_property_resource(getThis(), "ffmpeg_movie", ffmovie_ctx->rsrc_id);

    efree(argv);
    if (fullpath) {
        efree(fullpath);
    }
    if (hashkey) {
        efree(hashkey);
    }
}