Commit 87481f59 by 杜祥龙

初次提交

parent f7f63f57
CC=gcc
CFLAGS=-Wall -Wextra -g -O0
TARGET=a.out
SRCS=$(wildcard *.c)
default:
$(CC) -o $(TARGET) $(SRCS) $(CFLAGS)
clean:
rm -rf $(TARGET)
# 氦氪HEKR模块串口透传协议参考实现
[氦氪HEKR模块串口透传协议](http://docs.hekr.me/v4/%E7%A1%AC%E4%BB%B6%E5%BC%80%E5%8F%91/%E9%80%9A%E4%BF%A1%E5%8D%8F%E8%AE%AE/%E4%B8%B2%E5%8F%A3%E9%80%8F%E4%BC%A0%E5%8D%8F%E8%AE%AE/)
[48透传协议/2G模块协议](http://docs.hekr.me/v4/%E7%A1%AC%E4%BB%B6%E5%BC%80%E5%8F%91/%E9%80%9A%E4%BF%A1%E5%8D%8F%E8%AE%AE/48%E9%80%8F%E4%BC%A0%E5%8D%8F%E8%AE%AE/)
\ No newline at end of file
/* Hekr '48-Passthrough' Protocol
* Copyright(c) 2018 Hangzhou District Nine Technology Co., Ltd. */
#include "md5sum.h"
#include "hekr48trans.h"
#define PRODKEY_LEN (32)
#define DEVTID_LEN (32)
#define DEVPRIKEY_LEN (32)
#define RANDOMKEY_LEN (32)
#define CMD_REQUEST_VERIFY '1'
#define CMD_VERIFY '3'
#define CMD_HEARTBEAT 'B'
#define CMD_APPSENDRESP '8'
#define CMD_DEVSEND '9'
static ra_size_t _strlen(const char *s)
{
ra_size_t len = 0;
const char *p = s;
while (*p++ != '\0') len++;
return len;
}
static void *_memcpy(void *dest, const void *src, ra_size_t n)
{
char *dest_p = dest;
const char *src_p = src;
while (n-- != 0)
{
*dest_p++ = *src_p++;
}
return dest;
}
/* 0x0A -> "0A", by 2 */
int raw_to_hexlit(char *dst, const ra_u8 *src, ra_size_t len)
{
const ra_u8 *src_p = src;
char *dst_p = dst;
if (len == 0) return -1;
while (len-- != 0)
{
#define _x(_s) \
do { *dst_p++ = "0123456789ABCDEF"[_s]; } while (0)
_x((*src_p) >> 4);
_x((*src_p) & 0xF);
src_p++;
#undef _x
}
*dst_p = '\0';
return (int)(dst_p - dst);
}
/* "0A" -> 0x0A, by 2 */
int hexlit_to_raw(ra_u8 *dst, const char *src, const ra_size_t len)
{
ra_size_t i;
ra_u8 *dst_p = dst;
const char *src_p = src;
if ((len & 1) != 0) { return -1; }
for (i = 0; i != len; i += 2)
{
ra_u8 t_hi, t_lo;
#define _x(_d, _s) \
do { \
if ('0' <= _s && _s <= '9') { _d = (ra_u8)(_s - '0'); } \
else if ('a' <= _s && _s <= 'f') { _d = (ra_u8)(_s - 'a' + 10); } \
else if ('A' <= _s && _s <= 'F') { _d = (ra_u8)(_s - 'A' + 10); } \
else return -1; \
} while (0)
_x(t_hi, *src_p); src_p++;
_x(t_lo, *src_p); src_p++;
#undef _x
*dst_p++ = (ra_u8)((t_hi << 4) | (t_lo));
}
return (int)(dst_p - dst);
}
int hexlit_to_raw16(ra_u16 *dst, const char *src, const ra_size_t len)
{
ra_u8 hi, lo;
if (len != 4) return -1;
hexlit_to_raw(&hi, src, 2);
hexlit_to_raw(&lo, src + 2, 2);
*dst = ((ra_u16)hi << 8) | ((ra_u16)lo);
return 0;
}
static ra_u8 checksum8(ra_u8 *data, ra_size_t len)
{
ra_u32 cs = 0;
ra_u8 *p = data;
while (len != 0)
{
ra_u8 t;
if (hexlit_to_raw(&t, (const char *)p, 2) < 0)
{
/* Error */
return 0;
}
cs += t;
p += 2;
len -= 2;
}
return cs & 0xFF;
}
int h48_build_frame_verify_request(ra_u8 *buf, const ra_size_t buf_size, \
const ra_u8 frame_num, const char *prodkey, const char *devtid)
{
if (_strlen(prodkey) != PRODKEY_LEN) return -1;
if (_strlen(devtid) != DEVTID_LEN) return -1;
if (buf_size < 8 + PRODKEY_LEN * 2 + DEVTID_LEN * 2 + 2) return -1;
buf[0] = '4'; buf[1] = '8'; /* 48 */
buf[2] = '4'; buf[3] = '5'; /* length */
buf[4] = '0'; buf[5] = CMD_REQUEST_VERIFY; /* command */
raw_to_hexlit((char *)buf + 6, &frame_num, 1); /* frame number */
raw_to_hexlit((char *)buf + 8, (const ra_u8 *)prodkey, (ra_size_t)_strlen(prodkey)); /* prodkey */
raw_to_hexlit((char *)buf + 8 + PRODKEY_LEN * 2, (const ra_u8 *)devtid, (ra_size_t)_strlen(devtid)); /* prodkey */
{
ra_u8 cs = checksum8(buf, 8 + PRODKEY_LEN * 2 + DEVTID_LEN * 2);
raw_to_hexlit((char *)buf + 8 + PRODKEY_LEN * 2 + DEVTID_LEN * 2, &cs, 1);
}
return 8 + PRODKEY_LEN * 2 + DEVTID_LEN * 2 + 2;
}
int h48_build_frame_verify(ra_u8 *buf, const ra_size_t buf_size, \
const ra_u8 frame_num, const char *randomkey, const char *devtid, const char *devprikey)
{
if (_strlen(randomkey) != RANDOMKEY_LEN) return -1;
if (_strlen(devtid) != DEVTID_LEN) return -1;
if (_strlen(devprikey) != DEVPRIKEY_LEN) return -1;
if (buf_size < 8 + 16 * 2 + 2) return -1;
#if 0
printf("randomkey: %s\n", randomkey);
printf("devtid: %s\n", devtid);
printf("devprikey: %s\n", devprikey);
#endif
buf[0] = '4'; buf[1] = '8'; /* 48 */
buf[2] = '1'; buf[3] = '5'; /* length */
buf[4] = '0'; buf[5] = CMD_VERIFY; /* command */
raw_to_hexlit((char *)buf + 6, &frame_num, 1); /* frame number */
{
/* Compute AuthKey */
MD5_CTX context;
unsigned char md5_digest[16];
MD5Init(&context);
MD5Update(&context, (unsigned char *)randomkey, (ra_size_t)RANDOMKEY_LEN);
MD5Update(&context, (unsigned char *)devtid, (ra_size_t)DEVTID_LEN);
MD5Update(&context, (unsigned char *)devprikey, (ra_size_t)DEVPRIKEY_LEN);
MD5Final(&context, md5_digest);
raw_to_hexlit((char *)buf + 8, md5_digest, 16);
#if 0
printf("authkey: ");
fwrite(buf + 8, 32, 1, stdout);
printf("\n");
#endif
}
{
ra_u8 cs = checksum8(buf, 8 + 16 * 2);
raw_to_hexlit((char *)buf + 8 + 16 * 2, &cs, 1);
}
return 8 + 16 * 2 + 2;
}
int h48_build_frame_heartbeat(ra_u8 *buf, const ra_size_t buf_size, \
const ra_u8 frame_num)
{
if (buf_size < 8 + 2) return -1;
buf[0] = '4'; buf[1] = '8'; /* 48 */
buf[2] = '0'; buf[3] = '5'; /* length */
buf[4] = '0'; buf[5] = CMD_HEARTBEAT; /* command */
raw_to_hexlit((char *)buf + 6, &frame_num, 1); /* frame number */
{
ra_u8 cs = checksum8(buf, 8);
raw_to_hexlit((char *)buf + 8, &cs, 1);
}
return 8 + 2;
}
int h48_build_frame_devsend(ra_u8 *buf, const ra_size_t buf_size, const ra_u8 frame_num, const ra_u16 msgid, \
const ra_u8 *data, const ra_size_t data_len)
{
if (buf_size < 12 + data_len + 2) return -1;
buf[0] = '4'; buf[1] = '8'; /* 48 */
{
ra_u8 frame_len = (ra_u8)(6 + (data_len >> 1)) + 1;
raw_to_hexlit((char *)buf + 2, &frame_len, 1); /* length */
}
buf[4] = '0'; buf[5] = CMD_DEVSEND; /* command */
raw_to_hexlit((char *)buf + 6, &frame_num, 1); /* frame number */
{
ra_u8 msgid_hi = (ra_u8)(msgid >> 8);
ra_u8 msgid_lo = (ra_u8)(msgid & 0xFF);
raw_to_hexlit((char *)buf + 8, &msgid_hi, 1); /* msgid (hi) */
raw_to_hexlit((char *)buf + 10, &msgid_lo, 1); /* msgid (lo) */
}
_memcpy(buf + 12, data, data_len); /* data */
{
ra_u8 cs = checksum8(buf, 12 + data_len);
raw_to_hexlit((char *)buf + 12 + data_len, &cs, 1);
}
return (int)(12 + data_len + 2);
}
int h48_build_frame_appsendresp(ra_u8 *buf, const ra_size_t buf_size, const ra_u8 frame_num, const ra_u16 msgid, \
const ra_u8 *apptid)
{
if (buf_size < 74 * 2 + 2) return -1;
buf[0] = '4'; buf[1] = '8'; /* 48 */
buf[2] = '4'; buf[3] = 'B'; /* length */
buf[4] = '0'; buf[5] = CMD_APPSENDRESP; /* command */
raw_to_hexlit((char *)buf + 6, &frame_num, 1); /* frame number */
{
ra_u8 msgid_hi = (ra_u8)(msgid >> 8);
ra_u8 msgid_lo = (ra_u8)(msgid & 0xFF);
raw_to_hexlit((char *)buf + 8, &msgid_hi, 1); /* msgid (hi) */
raw_to_hexlit((char *)buf + 10, &msgid_lo, 1); /* msgid (lo) */
}
_memcpy(buf + 12, apptid, 64 * 2); /* apptid */
/* reserved */
{
int i;
for (i = 0; i != 8; i++)
{
buf[12 + 64 * 2 + i] = '0';
}
}
{
ra_u8 cs = checksum8(buf, 12 + 64 * 2 + 8);
raw_to_hexlit((char *)buf + 12 + 64 * 2 + 8, &cs, 1);
}
return 12 + 64 * 2 + 8 + 2;
}
h48_frame_type h48_frame_decode_type(ra_u8 *frame, const ra_size_t frame_size)
{
h48_frame_type ret;
ra_u8 v;
if (frame_size < 7) return H48_FRAME_TYPE_UNKNOWN;
hexlit_to_raw(&v, (const char *)frame + 4, 2);
switch (v)
{
case 0x07: ret = H48_FRAME_TYPE_APPSEND; break;
default: ret = H48_FRAME_TYPE_UNKNOWN; break;
}
return ret;
}
/* Hekr '48-Passthrough' Protocol
* Copyright(c) 2018 Hangzhou District Nine Technology Co., Ltd. */
#ifndef HEKR48TRANS_H
#define HEKR48TRANS_H
#include "ra_types.h"
typedef enum
{
H48_FRAME_TYPE_UNKNOWN,
H48_FRAME_TYPE_APPSEND,
} h48_frame_type;
int raw_to_hexlit(char *dst, const ra_u8 *src, ra_size_t len);
int hexlit_to_raw(ra_u8 *dst, const char *src, const ra_size_t len);
int hexlit_to_raw16(ra_u16 *dst, const char *src, const ra_size_t len);
int h48_build_frame_verify_request(ra_u8 *buf, const ra_size_t buf_size, const ra_u8 frame_num, \
const char *prodkey, const char *devtid);
int h48_build_frame_verify(ra_u8 *buf, const ra_size_t buf_size, const ra_u8 frame_num, \
const char *randomkey, const char *devtid, const char *devprikey);
int h48_build_frame_heartbeat(ra_u8 *buf, const ra_size_t buf_size, const ra_u8 frame_num);
int h48_build_frame_devsend(ra_u8 *buf, const ra_size_t buf_size, const ra_u8 frame_num, const ra_u16 msgid, \
const ra_u8 *data, const ra_size_t data_len);
int h48_build_frame_appsendresp(ra_u8 *buf, const ra_size_t buf_size, const ra_u8 frame_num, const ra_u16 msgid, \
const ra_u8 *apptid);
h48_frame_type h48_frame_decode_type(ra_u8 *frame, const ra_size_t frame_size);
#endif
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "usocket.h"
#include "hekr48trans.h"
#define HUB_HOST "hub.hekr.me"
#define HUB_PORT 87
#define FRAME48_BUF_LEN 255
typedef struct
{
usocket_t *fd;
ra_u16 msgid;
ra_u8 frame_num;
char *prodkey;
char *devtid;
char *devprikey;
} session;
static int login(session *sess)
{
ra_u8 buf[FRAME48_BUF_LEN];
char randomkey[32 + 1];
int len;
/* Send Verify Request */
{
if ((len = h48_build_frame_verify_request(buf, FRAME48_BUF_LEN, sess->frame_num++, sess->prodkey, sess->devtid)) < 0)
{
fprintf(stderr, "error: failed to build login frame\n");
return -1;
}
printf("D->C: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
if (usocket_send(sess->fd, buf, (ra_size_t)len) < len)
{ fprintf(stderr, "error: failed to send login frame\n"); return -1; }
if ((len = usocket_recv(sess->fd, buf, (ra_size_t)FRAME48_BUF_LEN)) < 0)
{ fprintf(stderr, "error: failed to receive login frame response\n"); return -1; }
printf("C->D: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
}
/* Verify */
{
/* Extract RandomKey */
memcpy(randomkey, buf + 8, 32);
randomkey[32] = '\0';
if ((len = h48_build_frame_verify(buf, FRAME48_BUF_LEN, sess->frame_num++, randomkey, sess->devtid, sess->devprikey)) < 0)
{ fprintf(stderr, "error: failed to build login frame\n"); return -1; }
printf("D->C: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
if (usocket_send(sess->fd, buf, (ra_size_t)len) < len)
{ fprintf(stderr, "error: failed to send login frame\n"); return -1; }
if ((len = usocket_recv(sess->fd, buf, (ra_size_t)FRAME48_BUF_LEN)) < 0)
{ fprintf(stderr, "error: failed to receive login frame response\n"); return -1; }
printf("C->D: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
}
return 0;
}
static int heartbeat(session *sess)
{
int len;
ra_u8 buf[FRAME48_BUF_LEN];
if ((len = h48_build_frame_heartbeat(buf, FRAME48_BUF_LEN, sess->frame_num++)) < 0)
{ fprintf(stderr, "error: failed to build heartbeat frame\n"); return -1; }
printf("D->C: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
if (usocket_send(sess->fd, buf, (ra_size_t)len) < len)
{ fprintf(stderr, "error: failed to send heartbeat frame\n"); return -1; }
if ((len = usocket_recv(sess->fd, buf, (ra_size_t)FRAME48_BUF_LEN)) < 0)
{ fprintf(stderr, "error: failed to receive heartbeat frame response\n"); return -1; }
printf("C->D: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
return 0;
}
static int reportdevinfo(session *sess)
{
int len;
ra_u8 buf[FRAME48_BUF_LEN];
static const char *data = "010000000000000000000000000000000000000000000000000000000000000000";
if ((len = h48_build_frame_devsend(buf, FRAME48_BUF_LEN, sess->frame_num++, sess->msgid++, \
(const ra_u8 *)data, (ra_size_t)strlen(data))) < 0)
{ fprintf(stderr, "error: failed to build devsend frame\n"); return -1; }
printf("D->C: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
if (usocket_send(sess->fd, buf, (ra_size_t)len) < len)
{ fprintf(stderr, "error: failed to send devsend frame\n"); return -1; }
if ((len = usocket_recv(sess->fd, buf, (ra_size_t)FRAME48_BUF_LEN)) < 0)
{ fprintf(stderr, "error: failed to receive devsend frame response\n"); return -1; }
printf("C->D: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
return 0;
}
static int appsendresp(session *sess, ra_u8 frame_num, ra_u16 msgid, const ra_u8 *apptid)
{
int len;
ra_u8 buf[FRAME48_BUF_LEN];
if ((len = h48_build_frame_appsendresp(buf, FRAME48_BUF_LEN, frame_num, msgid, apptid)) < 0)
{ fprintf(stderr, "error: failed to build appsendresp frame\n"); return -1; }
printf("D->C: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
if (usocket_send(sess->fd, buf, (ra_size_t)len) < len)
{ fprintf(stderr, "error: failed to send appsendresp frame\n"); return -1; }
return 0;
}
static int handle_appsend(session *sess)
{
int ret = 0;
ra_u8 buf[FRAME48_BUF_LEN];
int len;
ret = usocket_readable(sess->fd);
if (ret == -1)
{ fprintf(stderr, "error: failed to test connection\n"); return -1; }
else if (ret == 0) return 0;
if ((len = usocket_recv(sess->fd, buf, (ra_size_t)FRAME48_BUF_LEN)) < 0)
{ fprintf(stderr, "error: failed to receive devsend frame response\n"); return -1; }
printf("C->D: "); fwrite(buf, (size_t)len, 1, stdout); printf("\n");
{
h48_frame_type type = h48_frame_decode_type(buf, len);
switch (type)
{
case H48_FRAME_TYPE_UNKNOWN:
printf("unknown frame\n");
break;
case H48_FRAME_TYPE_APPSEND:
printf("appsend\n");
/* Response */
{
ra_u8 frame_num;
ra_u16 msgid;
const ra_u8 *apptid = buf + 5 * 2;
hexlit_to_raw(&frame_num, (const char *)buf + 3 * 2, 2);
hexlit_to_raw16(&msgid, (const char *)buf + 4 * 2, 4);
appsendresp(sess, frame_num, msgid, apptid);
}
/* TODO: Do things you should do */
break;
}
}
return 0;
}
static int loop(session *sess)
{
int tick = 0;
if (reportdevinfo(sess) != 0) { return -1; }
if (heartbeat(sess) != 0) { return -1; }
for (;;)
{
tick += 1;
if (tick == 5)
{
if (heartbeat(sess) != 0) { return -1; }
tick = 0;
}
handle_appsend(sess);
sleep(1);
}
return 0;
}
int main(int argc, char *argv[])
{
usocket_t fd;
session sess;
if (argc != 4)
{
fprintf(stderr, "usage: %s <prodkey> <devtid> <devprikey>\n", argv[0]);
return -1;
}
else
{
sess.prodkey = argv[1];
sess.devtid = argv[2];
sess.devprikey = argv[3];
}
/* Establish a TCP connection between your device and the 'hub' cloud */
usocket_init(&fd);
if (usocket_connect(&fd, HUB_HOST, HUB_PORT) != 0)
{
fprintf(stderr, "error: failed to connect to %s:%d\n", HUB_HOST, (int)HUB_PORT);
return -1;
}
sess.fd = &fd;
sess.frame_num = 0;
sess.msgid = 0;
/* Login */
if (login(&sess) != 0) { goto fail; }
/* Loop */
loop(&sess);
return 0;
fail:
return -1;
}
#include <memory.h>
#include "md5sum.h"
static unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void MD5Init(MD5_CTX *context)
{
context->count[0] = 0;
context->count[1] = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
}
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)
{
unsigned int i = 0,index = 0,partlen = 0;
index = (context->count[0] >> 3) & 0x3F;
partlen = 64 - index;
context->count[0] += inputlen << 3;
if(context->count[0] < (inputlen << 3))
context->count[1]++;
context->count[1] += inputlen >> 29;
if(inputlen >= partlen)
{
memcpy(&context->buffer[index],input,partlen);
MD5Transform(context->state,context->buffer);
for(i = partlen;i+64 <= inputlen;i+=64)
MD5Transform(context->state,&input[i]);
index = 0;
}
else
{
i = 0;
}
memcpy(&context->buffer[index],&input[i],inputlen-i);
}
void MD5Final(MD5_CTX *context,unsigned char digest[16])
{
unsigned int index = 0,padlen = 0;
unsigned char bits[8];
index = (context->count[0] >> 3) & 0x3F;
padlen = (index < 56)?(56-index):(120-index);
MD5Encode(bits,context->count,8);
MD5Update(context,PADDING,padlen);
MD5Update(context,bits,8);
MD5Encode(digest,context->state,16);
}
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)
{
unsigned int i = 0,j = 0;
while(j < len)
{
output[j] = input[i] & 0xFF;
output[j+1] = (input[i] >> 8) & 0xFF;
output[j+2] = (input[i] >> 16) & 0xFF;
output[j+3] = (input[i] >> 24) & 0xFF;
i++;
j+=4;
}
}
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)
{
unsigned int i = 0,j = 0;
while(j < len)
{
output[i] = ((unsigned int)input[j]) |
((unsigned int)input[j+1] << 8) |
((unsigned int)input[j+2] << 16) |
((unsigned int)input[j+3] << 24);
i++;
j+=4;
}
}
void MD5Transform(unsigned int state[4],unsigned char block[64])
{
unsigned int a = state[0];
unsigned int b = state[1];
unsigned int c = state[2];
unsigned int d = state[3];
unsigned int x[64];
MD5Decode(x,block,64);
FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */
HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
#ifndef MD5_H
#define MD5_H
typedef struct
{
unsigned int count[2];
unsigned int state[4];
unsigned char buffer[64];
}MD5_CTX;
#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
{ \
a += F(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define GG(a,b,c,d,x,s,ac) \
{ \
a += G(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define HH(a,b,c,d,x,s,ac) \
{ \
a += H(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define II(a,b,c,d,x,s,ac) \
{ \
a += I(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
void MD5Init(MD5_CTX *context);
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
void MD5Final(MD5_CTX *context,unsigned char digest[16]);
void MD5Transform(unsigned int state[4],unsigned char block[64]);
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
#endif
#ifndef RA_TYPES_H
#define RA_TYPES_H
typedef unsigned long long ra_u64;
typedef unsigned int ra_u32;
typedef unsigned short int ra_u16;
typedef unsigned char ra_u8;
typedef signed long long ra_s64;
typedef signed int ra_s32;
typedef signed short int ra_s16;
typedef char ra_s8;
typedef unsigned int ra_size_t;
#endif
#include <sys/time.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include "ra_types.h"
#include "usocket.h"
/* Initialize usocket */
void usocket_init( \
usocket_t *usocket)
{
usocket->type = USOCKET_TYPE_NONE;
}
/* If the fd is writable */
static int _writable(int fd, const int timeout)
{
fd_set wfds;
struct timeval tv;
int retval;
FD_ZERO(&wfds);
FD_SET(fd, &wfds);
tv.tv_sec = timeout;
tv.tv_usec = 0;
retval = select(fd + 1, NULL, &wfds, NULL, &tv);
if (retval == -1) return -1;
else if (retval == 0) return 0;
/* retval >= 0 */
return 1;
}
/* Connect to a plain host
* @return 0 success
* @return -1 fail */
int usocket_connect3( \
usocket_t *usocket, \
const char *host, const ra_size_t port, const int timeout, int blocking)
{
int ret = 0;
int fd = -1;
/* struct hostent *hent; */
struct sockaddr_in addr;
/* char *dst_p, *src_p; */
struct addrinfo *servinfo = NULL;
if (usocket->type != USOCKET_TYPE_NONE) { return -1; }
/* Resolve the host */
struct addrinfo hints;
char service_buf[16 + 1];
snprintf(service_buf, 16, "%d", (int)port);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo(host, service_buf, &hints, &servinfo) != 0)
{ ret = -1; goto fail; }
/* Fill address */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons((uint16_t)port);
memcpy(&addr.sin_addr, &((struct sockaddr_in *)servinfo->ai_addr)->sin_addr, sizeof(struct in_addr));
/* Create socket */
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{ ret = -1; goto fail; }
if (timeout == 0)
{
/* No timeout */
/* Connect */
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
{ ret = -1; goto fail; }
/* Non-block */
if (blocking == 0)
{
fcntl(fd, F_SETFL, O_NONBLOCK);
}
}
else
{
/* Non-block */
fcntl(fd, F_SETFL, O_NONBLOCK);
/* Connect */
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
{
if (errno != EINPROGRESS) { ret = -1; goto fail; }
if (!(_writable(fd, timeout) == 1)) { ret = -1; goto fail; }
{
int err;
socklen_t len = sizeof(int);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
{ ret = -1; goto fail; }
if (err != 0)
{ ret = -1; goto fail; }
}
}
/* Non-block */
if (blocking != 0)
{
const int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags & (~O_NONBLOCK));
}
}
usocket->type = USOCKET_TYPE_PLAIN;
usocket->u.as_plain.fd = fd;
goto done;
fail:
if (fd != -1) close(fd);
done:
if (servinfo != NULL)
{
freeaddrinfo(servinfo);
}
return ret;
}
/* Connect to a host */
int usocket_connect2( \
usocket_t *usocket, \
const char *host, const ra_size_t port, const int timeout)
{
return usocket_connect3(usocket, host, port, timeout, 1);
}
int usocket_connect( \
usocket_t *usocket, \
const char *host, const ra_size_t port)
{
return usocket_connect2(usocket, host, port, 0);
}
/* If the connection is alive */
int usocket_alive( \
usocket_t *usocket)
{
return usocket->type == USOCKET_TYPE_NONE ? 0 : 1;
}
/* Close */
void usocket_close( \
usocket_t *usocket)
{
switch (usocket->type)
{
case USOCKET_TYPE_NONE:
break;
case USOCKET_TYPE_PLAIN:
if (usocket->u.as_plain.fd != -1) close(usocket->u.as_plain.fd);
usocket->u.as_plain.fd = -1;
usocket->type = USOCKET_TYPE_NONE;
break;
}
}
/* If the fd is readable */
static int _readable(int fd)
{
fd_set rfds;
struct timeval tv;
int retval;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 1;
retval = select(fd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) return -1;
else if (retval) return 1;
return 0;
}
/* Readable */
int usocket_readable( \
usocket_t *usocket)
{
int ret = 0;
switch (usocket->type)
{
case USOCKET_TYPE_NONE:
ret = -1;
break;
case USOCKET_TYPE_PLAIN:
ret = _readable(usocket->u.as_plain.fd);
break;
}
return ret;
}
/* Recv */
int usocket_recv( \
usocket_t *usocket, \
void *buf, ra_size_t len)
{
int ret = 0;
switch (usocket->type)
{
case USOCKET_TYPE_NONE:
ret = -1;
break;
case USOCKET_TYPE_PLAIN:
ret = (int)recv(usocket->u.as_plain.fd, buf, len, 0);
break;
}
return ret;
}
/* Send */
int usocket_send( \
usocket_t *usocket, \
const void *buf, ra_size_t len)
{
int ret = 0;
switch (usocket->type)
{
case USOCKET_TYPE_NONE:
ret = -1;
break;
case USOCKET_TYPE_PLAIN:
ret = (int)send(usocket->u.as_plain.fd, buf, len, MSG_NOSIGNAL);
break;
}
return ret;
}
#ifndef USOCKET_H
#define USOCKET_H
#include "ra_types.h"
typedef enum
{
USOCKET_TYPE_NONE,
USOCKET_TYPE_PLAIN,
} usocket_type_t;
struct usocket
{
usocket_type_t type;
union
{
struct
{
int fd;
} as_plain;
} u;
};
typedef struct usocket usocket_t;
/* Initialize usocket */
void usocket_init( \
usocket_t *usocket);
/* Connect to a plain host
* @return 0 success
* @return -1 fail */
int usocket_connect3( \
usocket_t *usocket, \
const char *host, const ra_size_t port, const int timeout, int blocking);
/* Connect to a plain host
* @return 0 success
* @return -1 fail */
int usocket_connect2( \
usocket_t *usocket, \
const char *host, const ra_size_t port, const int timeout);
/* Connect to a plain host
* @return 0 success
* @return -1 fail */
int usocket_connect( \
usocket_t *usocket, \
const char *host, const ra_size_t port);
/* Test if the connection is established. */
int usocket_alive( \
usocket_t *usocket);
/* Close
* Disconnect the connection. */
void usocket_close( \
usocket_t *usocket);
/* Readable,
* For Plain socket. */
int usocket_readable( \
usocket_t *usocket);
/* Recv */
int usocket_recv( \
usocket_t *usocket, \
void *buf, ra_size_t len);
/* Send */
int usocket_send( \
usocket_t *usocket, \
const void *buf, ra_size_t len);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment