コード例 #1
0
ファイル: son.c プロジェクト: qiufengyu/CodeWarehouse
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程.
//所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的.
void* listen_to_neighbor(void* arg) {
	int i = *(int *)arg;
	int conn = nt[i].conn;
	sip_pkt_t* sip_pkt;
	while(1) {
		sip_pkt = (sip_pkt_t*)malloc(sizeof(sip_pkt_t));
		memset(sip_pkt, 0, sizeof(sip_pkt_t));
		if(recvpkt(sip_pkt, conn) > 0) {
				if(sip_pkt->header.type == SIP ) {
					printf("receive stcp packet from node %d\n", sip_pkt->header.src_nodeID);
				}
				forwardpktToSIP(sip_pkt, sip_conn);
		}
		else {
			//nt[i].conn = -1; wait for next connection
			close(conn);
			socklen_t clilen;
			struct sockaddr_in cli_addr;
			clilen = sizeof(cli_addr);
			conn = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
			int node = topology_getNodeIDfromip(&cli_addr.sin_addr);
			nt_addconn(nt, node, conn);
		}
		free(sip_pkt);
	}
}
コード例 #2
0
ファイル: son.c プロジェクト: BlackKD/SimpleNetFinall
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程.
//所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的.
void* listen_to_neighbor(void* arg) {
    while(1)
    {
        sip_pkt_t* pkt = (sip_pkt_t*)malloc(sizeof(sip_pkt_t));
        memset(pkt,0,sizeof(sip_pkt_t));
        if(recvpkt(pkt, nt[*((int *)arg)].conn) != -1)
            forwardpktToSIP(pkt,sip_conn);
        else
        {
            //sip_pkt_t* pkt = (sip_pkt_t*)malloc(sizeof(sip_pkt_t));
            memset(pkt,0,sizeof(sip_pkt_t));
            pkt->header.src_nodeID = topology_getMyNodeID();
            //printf("send neb my iD : %d\n",pkt->header.src_nodeID);
            pkt->header.dest_nodeID = nt[*((int *)arg)].nodeID;
            pkt->header.length = 0;
            pkt->header.type = SLEEP;
            forwardpktToSIP(pkt,sip_conn);
            nt[*((int *)arg)].conn = -1;
            return 0;
        }
        printf("send packet to IP\n");

    }
  return 0;
}
コード例 #3
0
ファイル: son.c プロジェクト: 2bdenny/Lab10_SimpleNet
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程.
//所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. 
void* listen_to_neighbor(void* arg) {
	int index = *(int *)arg;
//	printf("MSG: listen to neighbor node=%d\n", nt[index].nodeID);
	sip_pkt_t tmp;
	if (nt[index].conn == -1) {
		print_pos();
		printf("ERROR: connect not set for node %d\n", nt[index].nodeID);
		pthread_exit(NULL);
	}
	while (1) {
		memset(&tmp, 0, sizeof(sip_pkt_t));
		// recv a pkt from son
//		print_pos();
//		printf("MSG: prepare to recvpkt from socket=%d\n", nt[index].conn);
		int result;
		result = recvpkt(&tmp, nt[index].conn);
		if (result == -1){
			print_pos();
			printf("ERROR: recvpkt from neighbor node=%d socket=%d failed\n", nt[index].nodeID, nt[index].conn);
			sleep(1);
		}
//		else printf("MSG: recvpkt sip_pkt_t ok, send to sip...\n");
		// forward the pkt to sip
		result = forwardpktToSIP(&tmp, sip_conn);
		if (result == -1){
			print_pos();
			printf("ERROR: forward pkt to sip failed\n");
		}
//		else printf("MSG: send to sip ok\n");
	}
  	pthread_exit(NULL);
}
コード例 #4
0
ファイル: common.cpp プロジェクト: solb/nethashhash
// Reads a value from the given network socket.
// Accepts: file descriptor, caller-owned buffer, spot for the (newly) allocated buffer's length
// Returns: whether a file was received reasonably
bool hashhash::recvfile(int sfd, char **data, size_t *dlen) {
	size_t cap = MAX_PACKET_LEN-3+1;
	*data = (char *)malloc(cap);
	*dlen = 0;

	uint16_t llen;

	do {
		if(cap-*dlen <= MAX_PACKET_LEN-3) {
			// The buffer won't fit the next packet!
			char *buf = (char*)malloc(cap*2);
			memcpy(buf, *data, cap);
			free(*data);
			*data = buf;
			cap *= 2;
		}

		char *line;
		if(!recvpkt(sfd, OPC_STF, &line, NULL, &llen, false))
			return false; // bad shit happened
		memcpy(*data+*dlen, line, llen);
		free(line);
		*dlen += llen;
	}
	while(llen);

	(*data)[*dlen] = '\0';
	
	return true;
}
コード例 #5
0
ファイル: son.c プロジェクト: Kingci/NetlLab
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程.
//所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. 
void* listen_to_neighbor(void* arg) {
	sip_pkt_t* pkt = (sip_pkt_t *)malloc(sizeof(sip_pkt_t));
	while(1){
		memset(pkt, 0, sizeof(sip_pkt_t));
		if(recvpkt(pkt,nt[*(int *)arg].conn) > 0)
			forwardpktToSIP(pkt, sip_conn);
		else
			pthread_exit(NULL);
	}
}
コード例 #6
0
ファイル: son.c プロジェクト: tzzcl/simplenet
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程.
//所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的.
void* listen_to_neighbor(void* arg) {
	//你需要编写这里的代码.
	int now=(*(int*)arg);
	sip_pkt_t* data=malloc(sizeof(sip_pkt_t));
	memset(data,0,sizeof(sip_pkt_t));
	while (1){
		if (recvpkt(data,nt[now].conn)<0) 
		{
			close(nt[now].conn);
			//forwardpktToSIP(build_failpkt(nt[now].nodeID),sip_conn);
			break;
		}
		forwardpktToSIP(data,sip_conn);
	}
	free(data);
}
コード例 #7
0
ファイル: son.c プロジェクト: dsknight/SimpleNet
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程.
//所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. 
void* listen_to_neighbor(void* arg) {
    nbr_entry_t currNbr = nt[*(int *)arg];
    int conn = currNbr.conn;
    sip_pkt_t pkt;
    while(1){
        if (recvpkt(&pkt,conn) == 1){
            printf("recv a pkt from nbr %d\n",currNbr.nodeID);
            if(forwardpktToSIP(&pkt,sip_conn) < 0)
                printf("Error in send pkt to SIP\n");
        } else {
            printf("Error when try to recvpkt from neighbor\n");
            printf("connect lost, exit\n");
            close(nt[*(int *)arg].conn);
            nt[*(int *)arg].conn = -1;
            break;
        }
    }
    printf("Error in recvpkt\n");
    return 0;
}
コード例 #8
0
ファイル: lamport.c プロジェクト: DistAlgo/distalgo
void yield(int block)
{
    /* Called by the main thread to indicate willingness to relinquish
     * control. Corresponds to a "label". If block is NULL, yield() will
     * return immediately if there is no work to be done (no pending
     * packets). Otherwise, yield() will block until the next packet
     * arrives. */
    int flag = 0, r;
    packet_t pack;

l:
    r = recvpkt(g.sockfd, &pack, block);
    if (r > 0)
        handle_message(&pack);
    else if (r < 0) {
        /* Retry connection */
        close(g.sockfd);
        client_connect();
        goto l;
    }
}
コード例 #9
0
/* The heart of (S)NTP, exchange NTP packets and compute values to correct the local clock */
int
on_wire (
	struct addrinfo *host,
	struct addrinfo *bcast
	)
{
	char addr_buf[INET6_ADDRSTRLEN];
	register int try;
	SOCKET sock;
	struct key *pkt_key = NULL;
	int key_id = 0;
	struct timeval tv_xmt;
	struct pkt x_pkt;
	int error, rpktl, handle_pkt_res;


	if (ENABLED_OPT(AUTHENTICATION)) {
		key_id = (int) atol(OPT_ARG(AUTHENTICATION));
		get_key(key_id, &pkt_key);
	}
	for (try=0; try<5; try++) {
		memset(&r_pkt, 0, sizeof rbuf);
		
		error = GETTIMEOFDAY(&tv_xmt, (struct timezone *)NULL);
		tv_xmt.tv_sec += JAN_1970;

#ifdef DEBUG
		printf("sntp on_wire: Current time sec: %i msec: %i\n", (unsigned int) tv_xmt.tv_sec, 
				(unsigned int) tv_xmt.tv_usec);
#endif

		if (bcast) {
			create_socket(&sock, (sockaddr_u *)bcast->ai_addr);
			rpktl = recv_bcst_pkt(sock, &r_pkt, sizeof rbuf, (sockaddr_u *)bcast->ai_addr);
			closesocket(sock);
		} else {
			int pkt_len = generate_pkt(&x_pkt, &tv_xmt, key_id, pkt_key);

			create_socket(&sock, (sockaddr_u *)host->ai_addr);
			sendpkt(sock, (sockaddr_u *)host->ai_addr, &x_pkt, pkt_len);
			rpktl = recvpkt(sock, &r_pkt, sizeof rbuf, &x_pkt);
			closesocket(sock);
		}

		handle_pkt_res = handle_pkt(rpktl, &r_pkt, host);
		if (handle_pkt_res < 1)
			return handle_pkt_res;
	}

	getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
	msyslog(LOG_DEBUG, "Received no useable packet from %s!", addr_buf);

	return -1;
}

/* Compute the 8 bits for li_vn_mode */
void
set_li_vn_mode (
	struct pkt *spkt,
	char leap,
	char version,
	char mode
	) 
{
	if (leap > 3) {
		msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3 using max. 3");
		leap = 3;
	}

	if (mode > 7) {
		msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3");
		mode = 3;
	}

	spkt->li_vn_mode  = leap << 6;
	spkt->li_vn_mode |= version << 3;
	spkt->li_vn_mode |= mode;
}

/* set_time corrects the local clock by offset with either settimeofday() or by default 
 * with adjtime()/adjusttimeofday().
 */
int
set_time(
	double offset
	)
{
	struct timeval tp;

	if (ENABLED_OPT(SETTOD)) {
		GETTIMEOFDAY(&tp, NULL);

		tp.tv_sec += (long)offset;
		tp.tv_usec += 1e6 * (offset - (long)offset);
		NORMALIZE_TIMEVAL(tp);

		if (SETTIMEOFDAY(&tp, NULL) < 0) {
			msyslog(LOG_ERR, "Time not set: settimeofday(): %m");
			return -1;
		}
		return 0;
	}

	tp.tv_sec = (long)offset;
	tp.tv_usec = 1e6 * (offset - (long)offset);
	NORMALIZE_TIMEVAL(tp);

	if (ADJTIMEOFDAY(&tp, NULL) < 0) {
		msyslog(LOG_ERR, "Time not set: adjtime(): %m");
		return -1;
	}
	return 0;
}
コード例 #10
0
main(int argc, char *argv[]) {
	setbuf(stdout, NULL);
	int sock;

	// check usage
	if (argc != 4) {
		fprintf(stderr, "usage : %s <username> <server_ip_address> <5945>\n", argv[0]);
		exit(1);
	}

	// get hooked on to the server
	sock = hooktoserver(argv[1], argv[2], atoi(argv[3]));

	if (sock == -1)
		exit(1);

	fflush(stdout);

	// Initialize FDs to zero.
	// Assign Input FD to client Fds.
	// Assign socked FD to client Fds.

	fd_set clientfds, tempfds;
	FD_ZERO(&clientfds);
	FD_ZERO(&tempfds);
	FD_SET(sock, &clientfds);
	FD_SET(0, &clientfds);

	while (1) {

		// Use tempfds as it will be overwritten on select call
		// We want clientfds to keep track of all connected fds.

		tempfds = clientfds;

		if (select(FD_SETSIZE, &tempfds, NULL, NULL, NULL) == -1) {
			perror("select");
			exit(4);
		}

		// For every fd in the list, if the fd is set, check if
		// that is socket fd. If so, then it means that it we
		// received some message from server. It can be a message
		// from different client or server death. Also if the fd
		// is 0, it means there is some input from the user.
		// Read that input and send it to the server.

		int fd;
		for (fd = 0; fd < FD_SETSIZE; fd++) {
			if (FD_ISSET(fd,&tempfds)) {
				if (fd == sock) {
					Packet *pkt;
					pkt = recvpkt(sock);
					if (!pkt) {

						// server killed, exit
						fprintf(stderr, "Server closed the connection.\n");
						exit(1);
					}

					// display the text
					if (pkt->type == EMAIL_MSG_TO_CLIENT) {
						printf("New email received !\n>> %s\n", pkt->text);
					}else if(pkt->type == WELCOME_MSG){

						// Received welcome message. Print it.
						printf(">> %s\n", pkt->text);

						// Send username to client.
						char msg[MAXMSGLEN];
						strcpy(msg, argv[1]);

						// fprintf(stderr, "user: %s", msg);
						sendpkt(sock, USER_NAME, strlen(msg) + 1, msg);

					}else if(pkt->type == SERVER_ERROR) {

						printf(">> %s\n", pkt->text);
					}
					else{
						fprintf(stderr, "error: unexpected reply from server\n");
						exit(1);
					}

					// free the message
					freepkt(pkt);
				}

				if (fd == 0) {
					char msg[MAXMSGLEN];

					if (!fgets(msg, MAXMSGLEN, stdin))
						exit(0);

					if (strncmp(msg, QUIT_STRING, strlen(QUIT_STRING)) == 0) {
						sendpkt(sock, CLOSE_CON, 0, NULL);
						break;
					}

					char * pch1, *pch2, *user, *ipaddr;
					pch1 = strstr(msg, " ");
					pch2 = strstr(msg, "@");

					if (pch1 == NULL || pch2 == NULL) {
						fprintf(stderr,
								"error: invalid e-mail format.\nsyntax: <recp_user>@<ip_addr> <mesg>\n");
						break;
					}

					if (pch1 < pch2)
					{
						fprintf(stderr, "error: user name cannot contain spaces.\n");
						fprintf(stderr,
								"error: invalid e-mail format.\nsyntax: <recp_user>@<ip_addr> <mesg>\n");
						break;
					}

					user = (char *) malloc((strlen(msg) - strlen(pch2) + 1)*sizeof(char));
					strncpy(user, msg, (strlen(msg) - strlen(pch2))*sizeof(char));
					user[strlen(msg) - strlen(pch2)] = '\0';

					// fprintf(stderr, "client: user: %s", user);

					if(strcmp(user,"") == 0)
					{
						fprintf(stderr, "error: no username entered.\n");
						free(user);
						break;
					}

					ipaddr = (char *) malloc(
							(strlen(pch2) - strlen(pch1))* sizeof(char));
					strncpy(ipaddr, msg + strlen(user) + 1,
							(strlen(pch2) - strlen(pch1) - 1) * sizeof(char));
					ipaddr[strlen(pch2) - strlen(pch1) - 1] = '\0';

					// fprintf(stderr, "server: ip: %s", ipaddr);

					struct sockaddr_in sa;
					int result = inet_pton(AF_INET, ipaddr, &(sa.sin_addr));
					if(result == 0){
						fprintf(stderr,
								"error: invalid ip-address format.\nsyntax: <recp_user>@<ip_addr> <mesg>\n");
						free(user);
						free(ipaddr);
						break;
					}

					char * mailmsg;
					mailmsg = (char *) malloc(strlen(pch1) * sizeof(char));
					strncpy(mailmsg,
							msg + strlen(user) + strlen(ipaddr) + 2,
							(strlen(pch1) - 1) * sizeof(char));
					mailmsg[strlen(pch1)-1] = '\0';

					// It is okay to have empty body in the email message.

					if(strlen(mailmsg) > 80)
					{
						fprintf(stderr, "error: mail message length can be atmost 80 characters.\n");
						free(user);
						free(ipaddr);
						free(mailmsg);
						break;
					}

					// fprintf(stderr, "server: mailmsg: %s", mailmsg);

					free(user);
					free(ipaddr);
					free(mailmsg);

					msg[strlen(msg) - 1] = '\0';
					sendpkt(sock, EMAIL_MSG_TO_SERVER, strlen(msg) + 1, msg);

				}
			}
		}
	}
}
コード例 #11
0
ファイル: ethercatbase.cpp プロジェクト: TABETA/SOEM
/** Non blocking receive frame function. Uses RX buffer and index to combine
* read frame with transmitted frame. To compensate for received frames that
* are out-of-order all frames are stored in their respective indexed buffer.
* If a frame was placed in the buffer previously, the function retreives it
* from that buffer index without calling ec_recvpkt. If the requested index
* is not already in the buffer it calls ec_recvpkt to fetch it. There are
* three options now, 1 no frame read, so exit. 2 frame read but other
* than requested index, store in buffer and exit. 3 frame read with matching
* index, store in buffer, set completed flag in buffer status and exit.
*
* @param[in] port        = port context struct
* @param[in] idx         = requested index of frame
* @param[in] stacknumber  = 0=primary 1=secondary stack
* @return Workcounter if a frame is found with corresponding index, otherwise
* EC_NOFRAME or EC_OTHERFRAME.
*/
int ecx_portt::inframe(int idx, int stacknumber)
{
	ec_stackT *stack = (stacknumber == 0)?
						&(this->stack):
						&(this->redport->stack);
	int rval = EC_NOFRAME;
	ec_bufT *rxbuf = &(*stack->rxbuf)[idx];
	/* check if requested index is already in buffer ? */
	if ((idx < EC_MAXBUF) && ((*stack->rxbufstat)[idx] == EC_BUF_RCVD))
	{
		/* return WKC */
		rval = rxbuf->retreive();
		/* mark as completed */
		(*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
	}
	else
	{
		EnterCriticalSection(&(this->rx_mutex));
		/* non blocking call to retrieve frame from socket */
		if (recvpkt(stacknumber))
		{
			rval = EC_OTHERFRAME;
			EtherNetHeader *ehp = stack->tempbuf->getEtherNetHeader();
			/* check if it is an EtherCAT frame */
			if (ehp->isEtherCATFrame())
			{
				EC_Header *ecp = stack->tempbuf->getECATHeader();
				uint8 idxf = ecp->getIndex();
				/* found index equals reqested index ? */
				if (idxf == idx)
				{
					/* yes, put it in the buffer array (strip ethernet header) */
					memcpy(rxbuf, ecp, (*stack->txbuflength)[idx] - sizeof(EtherNetHeader));
					/* return WKC */
					uint16 l = ecp->getElength();
					rval = rxbuf->getWorkCounterFromTempBuf(l);
					/* mark as completed */
					(*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
					/* store MAC source word 1 for redundant routing info */
					(*stack->rxsa)[idx] = ntohs(ehp->sa1);
				}
				/* check if index exist and someone is waiting for it */
				else if(idxf < EC_MAXBUF && (*stack->rxbufstat)[idxf] == EC_BUF_TX)
				{
					rxbuf = &(*stack->rxbuf)[idxf];
					/* put it in the buffer array (strip ethernet header) */
					memcpy(rxbuf, ecp, (*stack->txbuflength)[idxf] - sizeof(EtherNetHeader));
					/* mark as received */
					(*stack->rxbufstat)[idxf] = EC_BUF_RCVD;
					(*stack->rxsa)[idxf] = ntohs(ehp->sa1);
				}
				else
				{
					/* strange things happend */
				}
			}
		}
		LeaveCriticalSection(&(this->rx_mutex));

	}

	/* WKC if mathing frame found */
	return rval;
}
コード例 #12
0
ファイル: chatclient.c プロジェクト: maofeichen/InGMU
/* try to join a group */
int joinagroup(int sock)
{
  Packet *  pkt;
  char      bufr[MAXPKTLEN];
  char *    bufrptr;
  int       bufrlen;
  char *    gname;
  char *    mname;
  
  /* send a list group request */
  sendpkt(sock, LIST_GROUPS, 0, NULL);

  /* recv a list group reply */
  pkt = recvpkt(sock);
  if (!pkt) {
    fprintf(stderr, "error: server died\n");
    exit(1);
  }
  
  if (pkt->type != LIST_GROUPS) {
    fprintf(stderr, "error: unexpected reply from server\n");
    exit(1);
  }

  /* display groups */
  showgroups(pkt->lent, pkt->text);

  /* read in group name */
  printf("which group? ");
  fgets(bufr, MAXPKTLEN, stdin);
  bufr[strlen(bufr)-1] = '\0';

  /* may want to quit */
  if (strcmp(bufr, "") == 0 ||
      strncmp(bufr, QUIT_STRING, strlen(QUIT_STRING)) == 0) {
    close(sock);
    exit(0);
  }
  gname = strdup(bufr);

  /* read in member name */
  printf("what nickname? ");
  fgets(bufr, MAXPKTLEN, stdin);
  bufr[strlen(bufr)-1] = '\0';

  /* may want to quit */
  if (strcmp(bufr, "") == 0 ||
      strncmp(bufr, QUIT_STRING, strlen(QUIT_STRING)) == 0) {
    close(sock);
    exit(0);
  }
  mname = strdup(bufr);
    
  /* send a join group message */
  bufrptr = bufr;
  strcpy(bufrptr, gname);
  bufrptr += strlen(bufrptr) + 1;
  strcpy(bufrptr, mname);
  bufrptr += strlen(bufrptr) + 1;
  bufrlen = bufrptr - bufr;
  sendpkt(sock, JOIN_GROUP, bufrlen, bufr);

  /* read the reply */
  pkt = recvpkt(sock);
  if (!pkt) {
    fprintf(stderr, "error: server died\n");
    exit(1);
  }
  if (pkt->type != JOIN_ACCEPTED && pkt->type != JOIN_REJECTED) {
    fprintf(stderr, "error: unexpected reply from server\n");
    exit(1);
  }

  /* if rejected display the reason */
  if (pkt->type == JOIN_REJECTED) {
    printf("admin: %s\n", pkt->text);
    free(gname);
    free(mname);
    return(0);
  } else {
    printf("admin: joined '%s' as '%s'\n", gname, mname);
    free(gname);
    free(mname);
    return(1);
  }
}
コード例 #13
0
ファイル: chatclient.c プロジェクト: maofeichen/InGMU
/*--------------------------------------------------------------------*/
main(int argc, char *argv[])
{
  int  sock;

  /* check usage */
  if (argc != 1) {
    fprintf(stderr, "usage : %s\n", argv[0]);
    exit(1);
  }

  /* get hooked on to the server */
  sock = hooktoserver();
  if (sock == -1)
    exit(1);

  /* keep mingling */
  while (1) {
    /* try to join a group */
    if (!joinagroup(sock))
      continue;
    
    /* joined some group. keep chatting */
    while (1) {
      /*
	FILL HERE 
	use select() to watch simulataneously for
	input from keyboard and messages from server
      */
      
      if (/* FILL HERE: message from server? */) {
	Packet *pkt;
	pkt = recvpkt(sock);
	if (!pkt) {
	  /* server killed, exit */
	  fprintf(stderr, "error: server died\n");
	  exit(1);
	}

	/* display the text */
	if (pkt->type != USER_TEXT) {
	  fprintf(stderr, "error: unexpected reply from server\n");
	  exit(1);
	}
	printf("%s: %s", pkt->text,
	       pkt->text + strlen(pkt->text) + 1);
	freepkt(pkt);
      }

      if (/* FILL HERE: input from keyboard? */) {
	char      bufr[MAXPKTLEN];

	fgets(bufr, MAXPKTLEN, stdin);
	if (strncmp(bufr, QUIT_STRING, strlen(QUIT_STRING)) == 0) {
	  /* leaving group */
	  sendpkt(sock, LEAVE_GROUP, 0, NULL);
	  break;
	}

	/* send the text to the server */
	sendpkt(sock, USER_TEXT, strlen(bufr)+1, bufr);
      }
    }
  }
}