int get_jpeg_snapshot(char* ip, char* data, int* len) { int sockfd; struct hostent *server; struct sockaddr_in serveraddr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { TL_ERROR("error opening socket : %d - %s", errno, strerror(errno)); return -1; } server = gethostbyname(ip); if (server == NULL) { TL_ERROR("no such host as %s", ip); return -1; } memset((char *) &serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; memcpy((char *)&serveraddr.sin_addr.s_addr, (char *)server->h_addr_list[0], server->h_length); serveraddr.sin_port = htons(80); if (connect(sockfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { TL_ERROR("error connecting : %d - %s", errno, strerror(errno)); return -1; } const char request_template[] = "GET /snap.jpg HTTP/1.1\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nCookie: VideoInput=1; VidType=MPEG4; Instance=1; gui=1; IsVideo1=1; IsVideo2=1; HcsoB=3f7154f44e371053; leasetimeid=1011325756\r\nConnection: keep-alive\r\n\r\n"; char request[500]; sprintf(request, request_template, ip); send(sockfd, request, strlen(request), 0); int read_len; int pos = 0; read_len = recv(sockfd, data+pos, 2048, 0); int jpeg_size; char* _pos = strstr(data, "Content-Length"); sscanf(_pos + strlen("Content-Length: "), "%d", &jpeg_size); _pos = strstr(data, "\r\n\r\n"); int to_read = jpeg_size - (read_len - ((_pos-data)+4)); while (to_read) { read_len = recv(sockfd, data+pos, 4096, 0); pos += read_len; to_read -= read_len; } *len = pos; return 0; }
int request_sps_pps(rcp_session* session, int coder, unsigned char* data, int *len) { rcp_packet req; *len = 0; init_rcp_header(&req, session->session_id, RCP_COMMAND_CONF_ENC_GET_SPS_AND_PPS, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_P_OCTET); req.numeric_descriptor = coder; rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; TL_INFO("resp action : %d", resp->action); tlog_hex(TLOG_DEBUG, "sps_pps_resp", resp->payload, resp->payload_length); memcpy(data, resp->payload, resp->payload_length); *len = resp->payload_length; return 0; error: TL_ERROR("request_sps_pps()"); return -1; }
int client_disconnect(rcp_session* session) { rcp_packet discon_req; init_rcp_header(&discon_req, session->session_id, RCP_COMMAND_CONF_DISCONNECT_PRIMITIVE, RCP_COMMAND_MODE_WRITE, RCP_DATA_TYPE_P_OCTET); discon_req.payload_length = 8; discon_req.payload[0] = 0x01; // connection disconnected discon_req.payload[1] = 0x01; // normal termination memcpy(discon_req.payload + 4, &con.ctrl_addr.sin_addr.s_addr, 4); rcp_packet* discon_resp = rcp_command(&discon_req); if (discon_resp == NULL) goto error; tlog_hex(TLOG_DEBUG, "client disconnect response", discon_resp->payload, discon_resp->payload_length); return 0; error: TL_ERROR("client_disconnect()"); return -1; }
rcp_packet* rcp_command(rcp_packet* req) { int res = rcp_send(req); if (res == -1) goto error; sem_wait(&resp_available[req->request_id]); if (resp[req->request_id].action == RCP_PACKET_ACTION_ERROR) { TL_ERROR("%s", error_str(resp[req->request_id].payload[0])); return NULL; } return &resp[req->request_id]; error: TL_ERROR("rcp_command()"); return NULL; }
int client_register(int user_level, const char* password, int type, int mode) { con.user_level = user_level; strcpy(con.password, password); rcp_packet reg_req; init_rcp_header(®_req, 0, RCP_COMMAND_CONF_RCP_CLIENT_REGISTRATION, RCP_COMMAND_MODE_WRITE, RCP_DATA_TYPE_P_OCTET); char pphrase[MAX_PASSPHRASE_LEN]; int plen; int res = generate_passphrase(mode, con.user_level, con.password, pphrase, &plen); if (res == -1) goto error; tlog_hex(TLOG_DEBUG, "passphrase", pphrase, plen); unsigned short tmp16; reg_req.payload[0] = type; reg_req.payload[1] = 0; tmp16 = htons(0); memcpy(reg_req.payload+2, &tmp16, 2); reg_req.payload[4] = mode; reg_req.payload[5] = plen; tmp16 = htons(1); memcpy(reg_req.payload+6, &tmp16, 2); tmp16 = htons(0xffff); memcpy(reg_req.payload+8, &tmp16, 2); memcpy(reg_req.payload+10, pphrase, plen); //cl_reg.payload[plen+10] = 0; reg_req.payload_length = plen + 10; //tlog_hex("client register payload", cl_reg.payload, cl_reg.payload_length); rcp_packet* reg_resp = rcp_command(®_req); if (reg_resp == NULL) goto error; tlog_hex(TLOG_DEBUG, "client register response", reg_resp->payload, reg_resp->payload_length); if (reg_resp->payload[0] == 0) goto error; con.user_level = reg_resp->payload[1]; con.client_id = ntohs(*(unsigned short*)(reg_resp->payload+2)); return 0; error: TL_ERROR("client_register()"); return -1; }
int client_unregister() { rcp_packet unreg_req; init_rcp_header(&unreg_req, 0, RCP_COMMAND_CONF_RCP_CLIENT_UNREGISTER, RCP_COMMAND_MODE_WRITE, RCP_DATA_TYPE_P_OCTET); rcp_packet* unreg_resp = rcp_command(&unreg_req); if (unreg_resp == NULL) goto error; int unregister_result = unreg_resp->payload[0]; if (unregister_result != 1) { TL_ERROR("unregister not successful"); return -1; } else return 0; error: TL_ERROR("client_unregister()"); return -1; }
int keep_alive(rcp_session* session) { rcp_packet alive_req; init_rcp_header(&alive_req, session->session_id, RCP_COMMAND_CONF_RCP_CONNECTIONS_ALIVE, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_F_FLAG); rcp_packet* alive_resp = rcp_command(&alive_req); if (alive_resp == NULL) goto error; return ntohl(*(unsigned int*)alive_resp->payload); error: TL_ERROR("keep_alive()"); return -1; }
int read_client_registration() { rcp_packet reg_req; init_rcp_header(®_req, 0, RCP_COMMAND_CONF_RCP_CLIENT_REGISTRATION, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_P_OCTET); rcp_packet* reg_resp = rcp_command(®_req); if (reg_resp == NULL) goto error; return 0; error: TL_ERROR("read_client_registration()"); return -1; }
int get_audio_stat() { rcp_packet req; init_rcp_header(&req, 0, RCP_COMMAND_CONF_AUDIO_ON_OFF, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_F_FLAG); req.numeric_descriptor = 0; rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; return resp->payload[0]; error: TL_ERROR("get_audio_stat()"); return -1; }
int request_intraframe(rcp_session* session) { rcp_packet req; init_rcp_header(&req, session->session_id, RCP_COMMAND_CONF_MPEG4_INTRA_FRAME_REQUEST, RCP_COMMAND_MODE_WRITE, RCP_DATA_TYPE_T_DWORD); memcpy(req.payload, (char*)&session->session_id, 4); rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; return 0; error: TL_ERROR("request_intraframe()"); return -1; }
int get_md5_random(unsigned char* md5) { rcp_packet md5_req; init_rcp_header(&md5_req, 0, RCP_COMMAND_CONF_RCP_REG_MD5_RANDOM, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_P_STRING); rcp_packet* md5_resp = rcp_command(&md5_req); if (md5_resp == NULL) goto error; TL_DEBUG("payload len = %d", md5_resp->payload_length); memcpy(md5, md5_resp->payload, md5_resp->payload_length); return 0; error: TL_ERROR("get_md5_random()"); return -1; }
int get_audio_input_level(int line) { rcp_packet req; init_rcp_header(&req, 0, RCP_COMMAND_CONF_AUDIO_INPUT_LEVEL, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_T_DWORD); req.numeric_descriptor = line; rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; tlog_hex(TLOG_INFO, "audio input level", resp->payload, resp->payload_length); return ntohl(*resp->payload); error: TL_ERROR("get_audio_input_level()"); return -1; }
int set_audio_stat(int on_off) { rcp_packet req; init_rcp_header(&req, 0, RCP_COMMAND_CONF_AUDIO_ON_OFF, RCP_COMMAND_MODE_WRITE, RCP_DATA_TYPE_F_FLAG); req.numeric_descriptor = 0; req.payload[0] = on_off; req.payload_length = 1; rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; return 0; error: TL_ERROR("set_audio_stat()"); return -1; }
static int rcp_recv() { int res; int len; int received; unsigned char buffer[RCP_MAX_PACKET_LEN]; res = recv(con.control_socket, buffer, TPKT_HEADER_LENGTH, 0); if (res == -1) goto error; len = ntohs(*(unsigned short*)(buffer+2)); len -= TPKT_HEADER_LENGTH; received = 0; while (received < len) { res = recv(con.control_socket, buffer+received, len-received, 0); if (res == -1) goto error; TL_DEBUG("%d bytes received", res); received += res; } tlog_hex(TLOG_DEBUG, "received", buffer, received); int request_id = get_request_id(buffer); rcp_packet* hdr = &resp[request_id]; read_rcp_header(buffer, hdr); memcpy(hdr->payload, buffer+RCP_HEADER_LENGTH, hdr->payload_length); return request_id; error: TL_ERROR("rcp_recv: %d - %s\n", errno, strerror(errno)); return -1; }
int set_audio_input_peek(int line, int peek) { rcp_packet req; init_rcp_header(&req, 0, RCP_COMMAND_CONF_AUDIO_INPUT_PEEK, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_T_DWORD); req.numeric_descriptor = line; *(unsigned long*)req.payload = htonl(peek); req.payload_length = 4; rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; tlog_hex(TLOG_INFO, "audio input peek", resp->payload, resp->payload_length); return ntohl(*resp->payload); error: TL_ERROR("set_max_audio_input_peek()"); return -1; }
static int rcp_send(rcp_packet* hdr) { unsigned char buffer[RCP_MAX_PACKET_LEN]; int len = hdr->payload_length + RCP_HEADER_LENGTH + TPKT_HEADER_LENGTH; write_TPKT_header(buffer, len); write_rcp_header(buffer+TPKT_HEADER_LENGTH, hdr); memcpy(buffer + RCP_HEADER_LENGTH + TPKT_HEADER_LENGTH, hdr->payload, hdr->payload_length); TL_DEBUG("sending %d bytes...", len); tlog_hex(TLOG_DEBUG, "data", buffer, len); int res = send(con.control_socket, buffer, len, 0); TL_DEBUG("%d sent", res); if (res == -1) TL_ERROR("unable to send packet: %d - %s", errno, strerror(errno)); return res; }
int set_mic_level(int line, int level) { rcp_packet req; init_rcp_header(&req, 0, RCP_COMMAND_CONF_AUDIO_MIC_LEVEL, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_T_DWORD); req.numeric_descriptor = line; *(unsigned long*)req.payload = htonl(level); req.payload_length = 4; rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; tlog_hex(TLOG_INFO, "audio mic level", resp->payload, resp->payload_length); return ntohl(*resp->payload); error: TL_ERROR("set_mic_level()"); return -1; }
int get_capability_list(cap_list* caps) { rcp_packet req; init_rcp_header(&req, 0, RCP_COMMAND_CONF_CAPABILITY_LIST, RCP_COMMAND_MODE_READ, RCP_DATA_TYPE_P_OCTET); rcp_packet* resp = rcp_command(&req); if (resp == NULL) goto error; //tlog_hex(TLOG_INFO, "cap list response", resp->payload, resp->payload_length); caps->version = ntohs(*(unsigned short*)(resp->payload + 2)); caps->section_count = ntohs(*(unsigned short*)(resp->payload + 4)); caps->sections = malloc(sizeof(cap_section) * caps->section_count); unsigned char* pos = resp->payload + 6; for (int i=0; i<caps->section_count; i++) { caps->sections[i].section_type = ntohs(*(unsigned short*)pos); pos += 2; caps->sections[i].section_size = ntohs(*(unsigned short*)pos); pos += 2; caps->sections[i].n_elems = ntohs(*(unsigned short*)pos); pos += 2; caps->sections[i].elements = malloc(sizeof(cap_element) * caps->sections[i].n_elems); for (int j=0; j<caps->sections[i].n_elems; j++) { caps->sections[i].elements[j].element_type = ntohs(*(unsigned short*)pos); pos += 2; switch (caps->sections[i].section_type) { case CAP_SECTION_TYPE_VIDEO: caps->sections[i].elements[j].identifier = ntohs(*(unsigned short*)pos); pos += 2; caps->sections[i].elements[j].compression = ntohs(*(unsigned short*)pos); pos += 2; caps->sections[i].elements[j].input_number = ntohs(*(unsigned short*)pos); pos += 2; caps->sections[i].elements[j].resolution = ntohs(*(unsigned short*)pos); pos += 2; break; case CAP_SECTION_TYPE_AUDIO: caps->sections[i].elements[j].identifier = ntohs(*(unsigned short*)pos); pos += 2; caps->sections[i].elements[j].compression = ntohs(*(unsigned short*)pos); pos += 2; break; case CAP_SECTION_TYPE_IO: case CAP_SECTION_TYPE_SERIAL: caps->sections[i].elements[j].identifier = ntohs(*(unsigned short*)pos); pos += 2; break; case CAP_SECTION_TYPE_CAMDATA: caps->sections[i].elements[j].input_number = ntohs(*(unsigned short*)pos); pos += 2; break; } } } return 0; error: TL_ERROR("capability_list()"); return -1; }
static int generate_passphrase(int mode, int user_level, char* password, char* pphrase, int* len) { char uname[20]; switch (user_level) { case RCP_USER_LEVEL_LIVE:strcpy(uname, "live");break; case RCP_USER_LEVEL_SERVICE:strcpy(uname, "service");break; case RCP_USER_LEVEL_USER:strcpy(uname, "user");break; default:break; } switch (mode) { case RCP_ENCRYPTION_MODE_PLAIN: sprintf(pphrase, "+%s:%s+", uname, password); *len = strlen(pphrase); break; case RCP_ENCRYPTION_MODE_MD5: { char instr[1000]; instr[0] = '+'; get_md5_random((unsigned char*)&instr[1]); //tlog_hex(TLOG_INFO, "md5 random str", &instr[1], 16); /* sprintf(&instr[17], "+++%s:%s+", uname, password); unsigned char response[16]; md5((unsigned char*)instr, strlen(instr), response); sprintf(pphrase, "+%s:%16s:%16s+", uname, "", ""); *len = strlen(uname) + 36; for (int i=0; i<16; i++) { pphrase[*len-17+i] = response[i]; pphrase[*len-33+i] = instr[1+i]; } */ unsigned char response[] = { 0x30, 0x37, 0x35, 0x64, 0x65, 0x30, 0x63, 0x30, 0x39, 0x36, 0x66, 0x33, 0x34, 0x38, 0x30, 0x31, 0x34, 0x61, 0x32, 0x63, 0x35, 0x34, 0x30, 0x37, 0x35, 0x39, 0x33, 0x38, 0x66, 0x31, 0x62, 0x34, }; sprintf(pphrase, "+%s:%16s:%32s+", uname, "", ""); *len = strlen(uname) + 2; for (int i=0; i<16; i++) pphrase[*len+i] = instr[1+i]; *len += 17; memcpy(pphrase + *len, response, 32); *len += 33; } break; default: TL_ERROR("generate_passphrase() - invalid encryption mode %d", mode); return -1; break; } return 0; }
int client_connect(rcp_session* session, int method, int media, int flags, rcp_media_descriptor* desc) { rcp_packet con_req; init_rcp_header(&con_req, 0, RCP_COMMAND_CONF_CONNECT_PRIMITIVE, RCP_COMMAND_MODE_WRITE, RCP_DATA_TYPE_P_OCTET); int len = 0; char* mdesc = con_req.payload; unsigned short tmp16; mdesc[0] = method; mdesc[1] = media; mdesc[2] = 0; mdesc[3] = flags; mdesc[4] = mdesc[5] = mdesc[6] = mdesc[7] = 0; mdesc[8] = desc->encapsulation_protocol; mdesc[9] = desc->substitude_connection | (desc->relative_addressing << 1); tmp16 = htons(desc->mta_port); memcpy(mdesc+10, &tmp16, 2); memcpy(mdesc+12, &desc->mta_ip, 4); mdesc[16] = desc->coder; mdesc[17] = desc->line; tmp16 = htons(desc->coding); memcpy(mdesc+24, &tmp16, 2); tmp16 = htons(desc->resolution); memcpy(mdesc+26, &tmp16, 2); mdesc[28] = 0; mdesc[29] = 0; tmp16 = htons(1000); memcpy(mdesc+30, &tmp16, 2); mdesc += 32; len += 32; con_req.payload_length = len; rcp_packet* con_resp = rcp_command(&con_req); if (con_resp == NULL) { printf("con_resp == NULL\n"); goto error; } TL_INFO("%s", connect_stat_str(con_resp->payload[2])); if (con_resp->payload[2] != 1) { printf("con_resp->payload[2] != 1\n"); goto error; } session->session_id = con_resp->session_id; TL_DEBUG("session id = %d - %d", con_resp->session_id, session->session_id); tlog_hex(TLOG_DEBUG, "client connection resp", con_resp->payload, con_resp->payload_length); desc->coder = con_resp->payload[16]; desc->line = con_resp->payload[17]; desc->coding = ntohs(*(unsigned short*)&con_resp->payload[24]); desc->resolution = ntohs(*(unsigned short*)&con_resp->payload[26]); return 0; error: TL_ERROR("client_connect()"); return -1; }