您好,登錄后才能下訂單哦!
rpc框架yar的打包邏輯主要集中在:
yar_packager.h、yar_packager.c、和packagers/json.c、packagers/msgpack.c、 packagers/php.c三個(gè)文件。
我從一個(gè)網(wǎng)站上找了下面協(xié)議,我們一會(huì)兒會(huì)用到body_len的部分,打包主要針對(duì)h色部分。
typedef struct _yar_packager {
const char *name;
int (*pack) (const struct _yar_packager *self, zval *pzval, smart_str *buf, char **msg);
zval * (*unpack) (const struct _yar_packager *self, char *content, size_t len, char **msg, zval *rret);
} yar_packager_t;
PHP_YAR_API int php_yar_packager_register(const yar_packager_t *packager);
PHP_YAR_API const yar_packager_t * php_yar_packager_get(char *name, int nlen);
struct _yar_packagers_list {
unsigned int size;
unsigned int num;
const yar_packager_t **packagers;
} yar_packagers_list;
php_yar_packager_get函數(shù)的具體實(shí)現(xiàn)如下,通過(guò)name獲得具體打包方式:
PHP_YAR_API const yar_packager_t * php_yar_packager_get(char *name, int nlen) /* {{{ */ {
int i = 0;
for (;i<yar_packagers_list.num;i++) {
if (strncasecmp(yar_packagers_list.packagers[i]->name, name, nlen) == 0) {
return yar_packagers_list.packagers[i];
}
}
return NULL;
} /* }}} */
然后是php_yar_packager_register,即把打包方式注冊(cè)到數(shù)組中。
// 首先 如果size=0,則分配5個(gè)空間,然后size=5。當(dāng)注冊(cè)數(shù)量從1到5,當(dāng)num達(dá)到size個(gè)的時(shí)候。
// 下次繼續(xù)size+=5。以此類推。
PHP_YAR_API int php_yar_packager_register(const yar_packager_t *packager) /* {{{ */ {
if (!yar_packagers_list.size) {
yar_packagers_list.size = 5;
yar_packagers_list.packagers = (const yar_packager_t **)malloc(sizeof(yar_packager_t *) * yar_packagers_list.size);
} else if (yar_packagers_list.num == yar_packagers_list.size) {
yar_packagers_list.size += 5;
yar_packagers_list.packagers = (const yar_packager_t **)realloc(yar_packagers_list.packagers, sizeof(yar_packager_t *) * yar_packagers_list.size);
}
yar_packagers_list.packagers[yar_packagers_list.num] = packager;
return yar_packagers_list.num++;
} /* }}} */
打包函數(shù)
zend_string *php_yar_packager_pack(char *packager_name, zval *pzval, char **msg) /* {{{ */ {
char header[8];
smart_str buf = {0};
// 如果有name, 通過(guò)name獲得具體的打包方式。否則則取全局的變量YAR_G(packager)。
const yar_packager_t *packager = packager_name ?
php_yar_packager_get(packager_name, strlen(packager_name)) : YAR_G(packager);
if (!packager) {
php_error_docref(NULL, E_ERROR, "unsupported packager %s", packager_name);
return 0;
}
memcpy(header, packager->name, 8);
// 初始化變量buf,然后先追加header,其實(shí)就是打包的名稱,占8個(gè)byte。
smart_str_alloc(&buf, YAR_PACKAGER_BUFFER_SIZE /* 1M */, 0);
smart_str_appendl(&buf, header, 8);
// 打包請(qǐng)求實(shí)體或者返回實(shí)體到buf中,并且返回。
packager->pack(packager, pzval, &buf, msg);
if (buf.s) {
smart_str_0(&buf);
return buf.s;
}
// 如果buf為空,則釋放內(nèi)容。
smart_str_free(&buf);
return NULL;
} /* }}} */
解包程序
// content 為傳入的字節(jié)流
zval * php_yar_packager_unpack(char *content, size_t len, char **msg, zval *rret) /* {{{ */ {
char *pack_info = content; /* 4 bytes, last byte is version */
const yar_packager_t *packager;
// 取得content對(duì)應(yīng)內(nèi)容的前8位,然后在第8為設(shè)置成'\0', 代表結(jié)束。然后content取得從第9位開(kāi)始的內(nèi)容。
// 記錄body的長(zhǎng)度則減去8位。
content = content + 8;
len -= 8;
*(pack_info + 7) = '\0';
packager = php_yar_packager_get(pack_info, strlen(pack_info));
if (!packager) {
spprintf(msg, 0, "unsupported packager '%s'", pack_info);
return NULL;
}
// 然后調(diào)用具體的解包程序解包
return packager->unpack(packager, content, len, msg, rret);
} /* }}} */
后面是注冊(cè)yar_packager_msgpack, yar_packager_php, yar_packager_json三種方式
#ifdef ENABLE_MSGPACK
php_yar_packager_register(&yar_packager_msgpack);
#endif
php_yar_packager_register(&yar_packager_php);
php_yar_packager_register(&yar_packager_json);
下面是json, msgpack, php三種打包方式具體實(shí)現(xiàn)。
主要以json格式對(duì)數(shù)據(jù)進(jìn)行打包和解包。
// 調(diào)用php_json擴(kuò)展進(jìn)行處理
int php_yar_packager_json_pack(const yar_packager_t *self, zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3))
php_json_encode(buf, pzval);
#else
php_json_encode(buf, pzval, 0); /* options */
#endif
return 1;
} /* }}} */
zval * php_yar_packager_json_unpack(const yar_packager_t *self, char *content, size_t len, char **msg, zval *rret) /* {{{ */ {
zval *return_value;
php_json_decode(rret, content, len, 1, 512);
return_value = rret;
return return_value;
} /* }}} */
依賴于msgpack的擴(kuò)展,關(guān)于msgpack的介紹,大家可以自己百度下。
// 這兩行應(yīng)該是 msgpack擴(kuò)展包里的函數(shù)。
extern void php_msgpack_serialize(smart_str *buf, zval *val);
extern void php_msgpack_unserialize(zval *return_value, char *str, size_t str_len);
int php_yar_packager_msgpack_pack(const yar_packager_t *self, zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
php_msgpack_serialize(buf, pzval);
return 1;
} /* }}} */
zval * php_yar_packager_msgpack_unpack(const yar_packager_t *self, char *content, size_t len, char **msg, zval *rret) /* {{{ */ {
zval *return_value;
ZVAL_NULL(rret);
php_msgpack_unserialize(rret, content, len); // 調(diào)用msgpack擴(kuò)展函數(shù)進(jìn)行
return_value = rret;
return return_value;
} /* }}} */
下面代碼應(yīng)該是利用php原生的serialize方法進(jìn)行解析。
int php_yar_packager_php_pack(const yar_packager_t *self, zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
php_serialize_data_t var_hash; // php_serialize_data_t 是在php_var.h中定義HashTable類型的指針
PHP_VAR_SERIALIZE_INIT(var_hash); // 初始化這個(gè)HashTable
php_var_serialize(buf, pzval, &var_hash); //
PHP_VAR_SERIALIZE_DESTROY(var_hash); // 銷毀掉這個(gè)HashTable
return 1;
} /* }}} */
zval * php_yar_packager_php_unpack(const yar_packager_t *self, char *content, size_t len, char **msg, zval *rret) /* {{{ */ {
zval *return_value;
const unsigned char *p;
php_unserialize_data_t var_hash;
p = (const unsigned char*)content;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
if (!php_var_unserialize(rret, &p, p + len, &var_hash)) {
zval_ptr_dtor(rret);
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
spprintf(msg, 0, "unpack error at offset %ld of %ld bytes", (long)((char*)p - content), len);
return NULL;
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
return_value = rret;
return return_value;
} /* }}} */
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。