usock.c

来自「Linux下gsm/gprs modem的看守程序。支持短信发送与接受。」· C语言 代码 · 共 1,745 行 · 第 1/4 页

C
1,745
字号
		 * <CR><LF>+CPBR: <index2>,<unmber>,<type>,<text>]]		 */		gp.index = er->tokens[0].u.numeric;		strlcpy(gp.numb, er->tokens[1].u.string, GSMD_PB_NUMB_MAXLEN+1);		gp.type = er->tokens[2].u.numeric;		strlcpy(gp.text, er->tokens[3].u.string, GSMD_PB_TEXT_MAXLEN+1);	}	else {		DEBUGP("Invalid Input : Parse error\n");		return -EINVAL;	}		talloc_free(er);	return gsmd_ucmd_submit(gu, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_READ,			cmd->id, sizeof(gp), &gp);}static int phonebook_readrg_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = ctx;	struct gsmd_phonebooks gps;	struct gsm_extrsp *er;	DEBUGP("resp: %s\n", resp);	er = extrsp_parse(cmd, resp);	if ( !er )		return -ENOMEM;	gps.is_last = (cmd->ret == 0 || cmd->ret == 4)? 1:0;	if ( !strncmp(resp, "OK", 2) ) {		/* The record is empty or could not read yet */		gps.pb.index = 0;	}	else if ( !strncmp(resp, "+CME", 4) ) {		DEBUGP("+CME error\n");		/* +CME ERROR: 21 */		gps.pb.index = 0 - atoi(strpbrk(resp, "0123456789"));	}	else if ( er->num_tokens == 4 &&			er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[1].type == GSMD_ECMD_RTT_STRING &&			er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[3].type == GSMD_ECMD_RTT_STRING ) {		/*		 * [+CPBR: <index1>,<number>,<type>,<text>[[...]		 * <CR><LF>+CPBR: <index2>,<unmber>,<type>,<text>]]		 */		gps.pb.index = er->tokens[0].u.numeric;		strlcpy(gps.pb.numb, er->tokens[1].u.string, GSMD_PB_NUMB_MAXLEN+1);		gps.pb.type = er->tokens[2].u.numeric;		strlcpy(gps.pb.text, er->tokens[3].u.string, GSMD_PB_TEXT_MAXLEN+1);	}	else {		DEBUGP("Invalid Input : Parse error\n");		return -EINVAL;	}		talloc_free(er);	return gsmd_ucmd_submit(gu, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_READRG,			cmd->id, sizeof(gps), &gps);}static int phonebook_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	DEBUGP("resp: %s\n", resp);	return gsmd_ucmd_submit(ctx, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_WRITE,			cmd->id, strlen(resp) + 1, resp);}static int phonebook_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	DEBUGP("resp: %s\n", resp);	return gsmd_ucmd_submit(ctx, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_DELETE,			cmd->id, strlen(resp) + 1, resp);}static int phonebook_get_support_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	/* TODO: Need to handle command error */	/* +CPBR: (1-100),44,16 */	struct gsmd_user *gu = ctx;	struct gsmd_phonebook_support gps;	char *fcomma, *lcomma;	char *dash;	DEBUGP("resp: %s\n", resp);	dash = strchr(resp, '-');	if (!dash)		return -EIO;	/* TODO: Send a response */	gps.index = atoi(dash + 1);	fcomma = strchr(resp, ',');	if (!fcomma)		return -EIO;	/* TODO: Send a response */	gps.nlength = atoi(fcomma+1);	lcomma = strrchr(resp, ',');	if (!lcomma)		return -EIO;	/* TODO: Send a response */	gps.tlength = atoi(lcomma+1);	return gsmd_ucmd_submit(gu,			GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_GET_SUPPORT,			cmd->id, sizeof(gps), &gps);}static int phonebook_list_storage_cb(struct gsmd_atcmd *cmd,		void *ctx, char *resp){	/* TODO; using link list ; need to handle command error */	struct gsmd_user *gu = ctx;	struct gsmd_phonebook_storage gps;	char *ptr;	DEBUGP("resp: %s\n", resp);	/*	 * +CPBS: (<storage>s)	 */	gps.num = 0;	if (!strncmp(resp, "+CPBS", 5)) {		char* delim = "(,";		ptr = strpbrk(resp, delim);		while (ptr) {			strncpy(gps.mem[gps.num].type, ptr + 2, 2);			gps.mem[gps.num].type[2] = '\0';			ptr = strpbrk(ptr + 2, delim);			gps.num++;		}	}	return gsmd_ucmd_submit(gu,			GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_LIST_STORAGE,			cmd->id, sizeof(gps), &gps);}static int usock_rcv_phonebook(struct gsmd_user *gu,		struct gsmd_msg_hdr *gph,int len){		struct gsmd_atcmd *cmd = NULL;	struct gsmd_phonebook_readrg *gpr;	struct gsmd_phonebook *gp;	struct gsmd_phonebook_find *gpf;	int *index;	int atcmd_len;	char *storage;	char buf[1024];	switch (gph->msg_subtype) {	case GSMD_PHONEBOOK_LIST_STORAGE:		cmd = atcmd_fill("AT+CPBS=?", 9 + 1,				&phonebook_list_storage_cb,				gu, gph->id, NULL);		break;	case GSMD_PHONEBOOK_SET_STORAGE:		if (len < sizeof(*gph) + 3)			return -EINVAL;		storage = (char*) ((void *)gph + sizeof(*gph));		/* ex. AT+CPBS="ME" */		atcmd_len = 1 + strlen("AT+CPBS=\"") + 2 + strlen("\"");		cmd = atcmd_fill("AT+CPBS=\"", atcmd_len,				&usock_cmd_cb, gu, gph->id, NULL);		if (!cmd)			return -ENOMEM;		sprintf(cmd->buf, "AT+CPBS=\"%s\"", storage);		break;	case GSMD_PHONEBOOK_FIND:		if(len < sizeof(*gph) + sizeof(*gpf))			return -EINVAL;		gpf = (struct gsmd_phonebook_find *) ((void *)gph + sizeof(*gph));		atcmd_len = 1 + strlen("AT+CPBF=\"") +			strlen(gpf->findtext) + strlen("\"");		cmd = atcmd_fill("AT+CPBF=\"", atcmd_len,				 &phonebook_find_cb, gu, gph->id, NULL);		if (!cmd)			return -ENOMEM;		sprintf(cmd->buf, "AT+CPBF=\"%s\"", gpf->findtext);		break;	case GSMD_PHONEBOOK_READ:		if(len < sizeof(*gph) + sizeof(int))			return -EINVAL;				index = (int *) ((void *)gph + sizeof(*gph));		sprintf(buf, "%d", *index);		/* ex, AT+CPBR=23 */		atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf);		cmd = atcmd_fill("AT+CPBR=", atcmd_len,				 &phonebook_read_cb, gu, gph->id, NULL);		if (!cmd)			return -ENOMEM;		sprintf(cmd->buf, "AT+CPBR=%d", *index);		break;	case GSMD_PHONEBOOK_READRG:				if(len < sizeof(*gph) + sizeof(*gpr))			return -EINVAL;		gpr = (struct gsmd_phonebook_readrg *) ((void *)gph + sizeof(*gph));		sprintf(buf, "%d,%d", gpr->index1, gpr->index2);				/* ex, AT+CPBR=1,100 */		atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf);		cmd = atcmd_fill("AT+CPBR=", atcmd_len,				 &phonebook_readrg_cb, gu, gph->id, NULL);		if (!cmd)			return -ENOMEM;		sprintf(cmd->buf, "AT+CPBR=%s", buf);		break;	case GSMD_PHONEBOOK_WRITE:		if(len < sizeof(*gph) + sizeof(*gp))			return -EINVAL;		gp = (struct gsmd_phonebook *) ((void *)gph + sizeof(*gph));		sprintf(buf, "%d,\"%s\",%d,\"%s\"",				gp->index, gp->numb, gp->type, gp->text);		atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf);		cmd = atcmd_fill("AT+CPBW=", atcmd_len,				 &phonebook_write_cb, gu, gph->id, NULL);		if (!cmd)			return -ENOMEM;		sprintf(cmd->buf, "AT+CPBW=%s", buf);		break;	case GSMD_PHONEBOOK_DELETE:		if(len < sizeof(*gph) + sizeof(int))			return -EINVAL;		index = (int *) ((void *)gph + sizeof(*gph));	    			sprintf(buf, "%d", *index);				/* ex, AT+CPBW=3*/		atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf);		cmd = atcmd_fill("AT+CPBW=", atcmd_len,				 &phonebook_delete_cb, gu, gph->id, NULL);		if (!cmd)			return -ENOMEM;		sprintf(cmd->buf, "AT+CPBW=%s", buf);		break;		case GSMD_PHONEBOOK_GET_SUPPORT:		cmd = atcmd_fill("AT+CPBR=?", 9+1,				 &phonebook_get_support_cb, gu, gph->id, NULL);		break;	default:		return -EINVAL;	}		if (cmd)		return atcmd_submit(gu->gsmd, cmd);	else		return 0;}static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = {	[GSMD_MSG_PASSTHROUGH]	= &usock_rcv_passthrough,	[GSMD_MSG_EVENT]	= &usock_rcv_event,	[GSMD_MSG_VOICECALL]	= &usock_rcv_voicecall,	[GSMD_MSG_PIN]		= &usock_rcv_pin,	[GSMD_MSG_PHONE]	= &usock_rcv_phone,	[GSMD_MSG_NETWORK]	= &usock_rcv_network,	[GSMD_MSG_SMS]		= &usock_rcv_sms,	[GSMD_MSG_CB]		= &usock_rcv_cb,	[GSMD_MSG_PHONEBOOK]	= &usock_rcv_phonebook,	[GSMD_MSG_MODEM]	= &usock_rcv_modem,};static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len){	struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf;	usock_msg_handler *umh;	if (gph->version != GSMD_PROTO_VERSION)		return -EINVAL;	if (gph->msg_type >= __NUM_GSMD_MSGS)		return -EINVAL;		umh = pcmd_type_handlers[gph->msg_type];	if (!umh)		return -EINVAL;	return umh(gu, gph, len);}/* callback for read/write on client (libgsmd) socket */static int gsmd_usock_user_cb(int fd, unsigned int what, void *data){	struct gsmd_user *gu = data;	/* FIXME: check some kind of backlog and limit it */	if (what & GSMD_FD_READ) {		char buf[1024];		int rcvlen;		/* read data from socket, determine what he wants */		rcvlen = read(fd, buf, sizeof(buf));		if (rcvlen == 0) {			DEBUGP("EOF, this client has just vanished\n");			/* EOF, this client has just vanished */			gsmd_unregister_fd(&gu->gfd);			close(fd);			/* finish pending atcmd's from this client thus			 * destroying references to the user structure.  */			atcmd_terminate_matching(gu->gsmd, gu);			/* destroy whole user structure */			llist_del(&gu->list);			talloc_free(gu);			return 0;		} else if (rcvlen < 0)			return rcvlen;		else			return usock_rcv_pcmd(gu, buf, rcvlen);	}	if (what & GSMD_FD_WRITE) {		/* write data from pending replies to socket */		struct gsmd_ucmd *ucmd, *uctmp;		llist_for_each_entry_safe(ucmd, uctmp, &gu->finished_ucmds,					  list) {			int rc;			rc = write(fd, &ucmd->hdr, sizeof(ucmd->hdr) + ucmd->hdr.len);			if (rc < 0) {				DEBUGP("write return %d\n", rc);				return rc;			}			if (rc == 0) {				DEBUGP("write returns zero!!\n");				break;			}			if (rc != sizeof(ucmd->hdr) + ucmd->hdr.len) {				DEBUGP("short write\n");				break;			}			DEBUGP("successfully sent cmd %p to user %p, freeing\n", ucmd, gu);			llist_del(&ucmd->list);			talloc_free(ucmd);		}		if (llist_empty(&gu->finished_ucmds))			gu->gfd.when &= ~GSMD_FD_WRITE;	}	return 0;}/* callback for read on master-listen-socket */static int gsmd_usock_cb(int fd, unsigned int what, void *data){	struct gsmd *g = data;	struct gsmd_user *newuser;	/* FIXME: implement this */	if (what & GSMD_FD_READ) {		/* new incoming connection */		newuser = talloc(__gu_ctx, struct gsmd_user);		if (!newuser)			return -ENOMEM;				newuser->gfd.fd = accept(fd, NULL, 0);		if (newuser->gfd.fd < 0) {			DEBUGP("error accepting incoming conn: `%s'\n",				strerror(errno));			talloc_free(newuser);		}		newuser->gfd.when = GSMD_FD_READ;		newuser->gfd.data = newuser;		newuser->gfd.cb = &gsmd_usock_user_cb;		newuser->gsmd = g;		newuser->subscriptions = 0xffffffff;		INIT_LLIST_HEAD(&newuser->finished_ucmds);		llist_add(&newuser->list, &g->users);		gsmd_register_fd(&newuser->gfd);	}	return 0;}/* handling of socket with incoming client connections */int usock_init(struct gsmd *g){	struct sockaddr_un sun;	int fd, rc;	__ucmd_ctx = talloc_named_const(gsmd_tallocs, 1, "ucmd");	__gu_ctx = talloc_named_const(gsmd_tallocs, 1, "gsmd_user");	fd = socket(PF_UNIX, GSMD_UNIX_SOCKET_TYPE, 0);	if (fd < 0)		return fd;		memset(&sun, 0, sizeof(sun));	sun.sun_family = AF_UNIX;	memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));	rc = bind(fd, (struct sockaddr *)&sun, sizeof(sun));	if (rc < 0) {		close(fd);		return rc;	}	rc = listen(fd, 10);	if (rc < 0) {		close(fd);		return rc;	}	g->gfd_sock.fd = fd;	g->gfd_sock.when = GSMD_FD_READ | GSMD_FD_EXCEPT;	g->gfd_sock.data = g;	g->gfd_sock.cb = &gsmd_usock_cb;	return gsmd_register_fd(&g->gfd_sock);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?