예제 #1
0
/*Send Request Message and Receive Response Message Function
  Variable Definition:
  -- client_socket: socket connected to the server
  -- node: request message node
  Return Value: received response message from server
*/
char *sendAndRcvdMessage(int client_socket, struct request_message *node){	
	char		*rcvd_buffer = (char*)malloc(sizeof(char) * (BUFFER_SIZE));	//received response message buffer
	ssize_t		bytes = 0;													//number of bytes

	//send request message to the server
	bytes = send(client_socket, node->message, node->message_length, MSG_NOSIGNAL);
	//Test the send is successful
	if (bytes < 0){
		dieWithSystemMessage("send() failed!");
	}
	else if (bytes != node->message_length){
		dieWithUserMessage("send()", "sent unexpected number of bytes");
	}
	//Receive Response Message from the server
	bytes = recv(client_socket, rcvd_buffer, BUFFER_SIZE - 1, 0);
	//Test the receive is successful
	if (bytes < 0){
		dieWithSystemMessage("recv() failed!");
	}
	else if (bytes == 0){
		dieWithUserMessage("recv()", "connection closed prematurely");
	}
	// NC: cool automated testing; you could also check the content of the result
	return rcvd_buffer;
}
/*Handle Client Request Function
  Variable Definition:
  -- client_socket: socket connected to the client
  Return Value: NULL
*/
void handleClientRequest(int client_socket) {
    FILE 	*channel;						//file stream for client socket
    char 	request_line[STRING_SIZE];		//client request line
    char	*return_value;					//each line header pointer

    //Initialize request_line buffer
    memset(request_line, 0, STRING_SIZE);
    //Create an input stream from the socket
    channel = fdopen(client_socket, "r");
    if (channel == NULL) {
        dieWithSystemMessage("fdopen() failed");
    }

    //Get client Request Line (Jump the blank line)
    do {
        return_value = fgets(request_line, STRING_SIZE, channel);
    } while (syntaxChecking(return_value, BLANK_LINE));
    //Output the client_socket id and Request Line
    printf("Got a call on %d: request = %s", client_socket, request_line);
    //Get client Header Lines & Response the client request
    respondClientRequest(request_line, getHeaderLines(channel), client_socket);

    //Close client socket
    close(client_socket);
    //Close file stream
    fclose(channel);

    return;
}
static int tioSioSocketInitTcp(unsigned short port)
{
    struct sockaddr_in addr;

    /* Create server socket */
    int sioSocketFd = socket(AF_INET, SOCK_STREAM, 0);
    if (sioSocketFd == -1) {
        dieWithSystemMessage("socket()");
    }

    /* Construct server address, and make the connection */
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(LOCALHOST_ADDR);
    addr.sin_port = htons(port);

    if (connect(sioSocketFd, (struct sockaddr *)&addr,
        sizeof(struct sockaddr)) == -1) {
        /* connection to sio_agent was not established */
        close(sioSocketFd);
        sioSocketFd = -1;
    }

    return sioSocketFd;
}
static int tioSioSocketInitUnix(const char *socketName)
{
    struct sockaddr_un addr;

    /* Create server socket */
    int sioSocketFd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sioSocketFd == -1) {
        dieWithSystemMessage("socket()");
    }

    /* Construct server address, and make the connection */
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX; 
    strncpy(addr.sun_path, socketName, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';

    if (connect(sioSocketFd, (struct sockaddr *)&addr,
        sizeof(struct sockaddr)) == -1) {
        /* connection to sio_agent was not established */
        close(sioSocketFd);
        sioSocketFd = -1;
    }

    return sioSocketFd;
}
예제 #5
0
/*Setup Server Socket Function
  Variable Definition:
  -- service: socket service name or port number
  Return value: server socket number
*/
int setupServerSocket(const char *service){
	struct addrinfo 		address_criteria;	//criteria for address match
	struct addrinfo 		*server_address;	//list of server addresses
	struct addrinfo 		*address;			//pointer to addresses node
	struct sockaddr_storage local_address;		//print local address
	socklen_t 				address_size;		//address size
	int 					server_socket = -1;	//socket descriptor for server
	int 					return_value;		//return value
	
	//Construct the server address structure
	memset(&address_criteria, 0, sizeof(address_criteria));	//zero the address_criteria
	address_criteria.ai_family = AF_UNSPEC;					//any address family
	address_criteria.ai_flags = AI_PASSIVE;					//accept on any address/port
	address_criteria.ai_socktype = SOCK_STREAM;				//only stream sockets
	address_criteria.ai_protocol = IPPROTO_TCP;				//only tcp protocol
	
	//Get address/name information
	return_value = getaddrinfo(NULL, service, &address_criteria, &server_address);
	//Success returns zero
	if (return_value != 0){
		dieWithUserMessage("getaddrinfo() failed!", gai_strerror(return_value));
	}
	
	//Create socket for incoming connections
	for (address = server_address; address != NULL; address = address->ai_next){
		//Initialize the server socket
		server_socket = -1;
		//Create socket for incoming connections
		server_socket = socket(server_address->ai_family, server_address->ai_socktype, server_address->ai_protocol);
		//if socket creation failed, try next address in the list
		if (server_socket < 0){
			continue;
		}
		
		//Bind to the server local address and set socket to the list
		if ((bind(server_socket, server_address->ai_addr, server_address->ai_addrlen) == 0) && 
				(listen(server_socket, MAX_PENDING) == 0)){
			//Get address size
			address_size = sizeof(local_address);
			//Get socket name
			if (getsockname(server_socket, (struct sockaddr*)&local_address, &address_size) < 0){
				dieWithSystemMessage("getsockname() failed!");
			}
			//Output local address and port of socket(listening address and port)
			fputs("Binding to ", stdout);
			printSocketAddress((struct sockaddr*)&local_address, stdout);
			fputc('\n', stdout);
			//Bind and list successful
			break;
		}
		//Close and try again
		close(server_socket);
	}
	//Free address list allocated by getaddrinfo()
	freeaddrinfo(server_address);
	
	return server_socket;
}
예제 #6
0
/*Accept Client Connection Function
  Variable Definition:
  -- server_socket: server socket number
  Return Value: connected client socket number
*/
int acceptConnection(int server_socket){
	struct sockaddr_storage client_address;			//client address
	socklen_t 				client_address_length;	//length of client address structure
	int 					client_socket;			//socket descriptor for client
	
	//Set length of client address structure
	client_address_length = sizeof(client_address);
	//Wait for a client to connect
	client_socket = accept(server_socket, (struct sockaddr*)&client_address, &client_address_length);
	if (client_socket < 0){
		dieWithSystemMessage("accept() failed!");
	}
	
	//Now, client_socket is connected to a client
	//Output the socket address and port
	fputs("Handling client ", stdout);
	printSocketAddress((struct sockaddr*)&client_address, stdout);
	fputc('\n', stdout);
	
	return client_socket;
}
/*Construct Response Message to Client Function
  Variable Definition:
  -- client_socket: socket connected to the client
  -- stream: file stream of socket or server file
  -- status_code: response status code
  -- status_message: response status message
  -- cseq_number: cseq number
  -- transport: transport field
  -- last_modified_time: response last modified time field
  -- content_length: response content length field
  -- content_type: response content type field
  -- content: response entity body field
  Return Value: bytes of whole message
*/
int	constructResponseMessage(	int				client_socket,
                                FILE 			**stream,
                                int				status_code,
                                const char		*status_message,
                                u_int32			cseq_number,
                                const char		*transport,
                                const char		*last_modified_time,
                                int				content_length,
                                const char		*content_type,
                                const char		*content) {
    FILE	*channel;		//file stream for client socket
    int		bytes = 0;		//bytes that send to client

    //Create an output stream to the socket
    channel = fdopen(client_socket, "w");
    if (channel == NULL) {
        dieWithSystemMessage("fopen() failed");
    }

    //Response Message Status Line
    bytes = fprintf(channel, "RTSP/1.0 %d %s%s", status_code, status_message, CRLF);
    //Response Cseq field
    if (cseq_number != 0) {
        bytes += fprintf(channel, "Cseq: %u%s", cseq_number, CRLF);
    }
    //Response Session field
    if (session_id != 0) {
        bytes += fprintf(channel, "Session: %u%s", session_id, CRLF);
    }
    //Response Transport field
    if (transport) {
        bytes += fprintf(channel, "Transport: %s%s", transport, CRLF);
    }
    //Response Date field
    bytes += fprintf(channel, "Date: %s%s", convertTimeFormat(getTimeInGMTFormat(NULL, 0), 1), CRLF);
    //Response Server field
    bytes += fprintf(channel, "Server: Data Communications & Networks: RTSP server by %s (Unix)%s", MY_NAME, CRLF);
    //Response Last-Modified field
    if (last_modified_time) {
        bytes += fprintf(channel, "Last-Modified: %s%s", last_modified_time, CRLF);
    }
    //Response Content-Length field
    if (content_length != 0) {
        bytes += fprintf(channel, "Content-Length: %d%s", content_length, CRLF);
    }
    //Response Message Content-Type field
    if (content_type) {
        bytes += fprintf(channel, "Content-Type: %s%s%s", content_type, CRLF, CRLF);
    }
    //Response Message Entity Body field
    if (content) {
        bytes += fprintf(channel, "%s%s", content, CRLF);
    }
    //Flush the channel
    fflush(channel);

    //Pass the stream
    if (stream) {
        *stream = channel;
    }
    else {
        //Close file stream
        fclose(channel);
    }

    return bytes;
}
int main(int argc, char** argv)
{
    const char *transFilePath = TIO_DEFAULT_TRANSLATION_FILE_PATH;
    unsigned refreshDelay = 0;   /* in seconds, 0 = disabled */
    const char *logFilePath = 0;
    /* 
     * syslog isn't installed on the target so it's disabled in this program
     * by requiring an argument to -o|--log.
     */ 
    int logToSyslog = 0;
    unsigned short sioPort = 0;  /* 0 means use Unix socket */
    unsigned short tioPort = 0;
    int daemonFlag = 0;
    int verboseFlag = 0;
    unsigned short mapSize = MAX_MSG_MAP_SIZE;

    /* allocate memory for progName since basename() modifies it */
    const size_t nameLen = strlen(argv[0]) + 1;
    char arg0[nameLen];
    memcpy(arg0, argv[0], nameLen);
    progName = basename(arg0);

    while (1) {
        static struct option longOptions[] = {
            { "daemon",     no_argument,       0, 'd' },
            { "file",       required_argument, 0, 'f' },
            { "map-size",   optional_argument, 0, 'm' },
            { "refresh",    optional_argument, 0, 'r' },
            { "sio_port",   optional_argument, 0, 's' },
            { "tio_port",   optional_argument, 0, 't' },
            { "verbose",    no_argument,       0, 'v' },
            { "help",       no_argument,       0, 'h' },
            { 0,            0, 0,  0  }
        };
        int c = getopt_long(argc, argv, "df:m:r::s::t::vh?", longOptions, 0);

        if (c == -1) {
            break;  // no more options to process
        }

        switch (c) {
        case 'd':
            daemonFlag = 1;
            break;

        case 'f':
            transFilePath = optarg;
            break;

        case 'm':
            mapSize = (optarg == 0) ? MAX_MSG_MAP_SIZE : atoi(optarg);
            break;

        case 'r':
            refreshDelay = (optarg == 0) ? DEFAULT_REFRESH_DELAY : atoi(optarg);
            break;

        case 's':
            sioPort = (optarg == 0) ? SIO_DEFAULT_AGENT_PORT : atoi(optarg);
            break;

        case 't':
            tioPort = (optarg == 0) ? TIO_DEFAULT_AGENT_PORT : atoi(optarg);
            break;

        case 'v':
            verboseFlag = 1;
            break;

        case 'h':
        case '?':
        default:
            tioDumpHelp();
            exit(1);
        }
    }

    /* set up logging to syslog or file; will be STDERR not told otherwise */
    LogOpen(progName, logToSyslog, logFilePath, verboseFlag);

    /* keep STDIO going for now */
    if (daemonFlag) {
        if (daemon(0, 1) != 0) {
            dieWithSystemMessage("daemon() failed");
        }
    }

    tioAgent(transFilePath, refreshDelay, tioPort, TIO_AGENT_UNIX_SOCKET,
        sioPort, SIO_AGENT_UNIX_SOCKET, mapSize);

    exit(EXIT_SUCCESS);
}
static void tioAgent(const char *translatePath, unsigned refreshDelay,
    unsigned short tioPort, const char *tioSocketPath, unsigned short sioPort,
    const char *sioSocketPath, const unsigned short mapSize)
{
    fd_set currFdSet;
    int connectedFd = -1;  /* not currently connected */
    time_t lastCheckTime = 0;
    time_t lastModTime = 0;
    int addressFamily = 0;

    TranslatorState *translatorState = GetTranslatorState();
    initTranslations(translatorState, mapSize);

    {
        /* install a signal handler to remove the socket file */
        struct sigaction a;
        memset(&a, 0, sizeof(a));
        a.sa_handler = tioInterruptHandler;
        if (sigaction(SIGINT, &a, 0) != 0) {
            LogMsg(LOG_ERR, "[TIO] sigaction(SIGINT) failed, errno = %d\n", errno);
            exit(1);
        }
        if (sigaction(SIGTERM, &a, 0) != 0) {
            LogMsg(LOG_ERR, "[TIO] sigaction(SIGTERM) failed, errno = %d\n", errno);
            exit(1);
        }
    }

    /* buffers for collection characters from each side */
    struct LineBuffer fromSio;
    fromSio.pos = 0;
    struct LineBuffer fromQv;
    fromQv.pos = 0;

    /* do initial load, may get reloaded in while loop, below */
    lastModTime = loadTranslations(translatorState, translatePath, 0);
    lastCheckTime = time(0);

    /* 
     * This is the select loop which waits for characters to be received on the
     * sio_agent descriptor and on either the listen socket (meaning an
     * incoming connection is queued) or on a connected socket descriptor.  If
     * not connected to the sio_agent, make select() time out to keep trying to
     * open a connection to it.
     */
    /* 100ms retry timeout for opening socket to sio_agent */
    struct  timeval timeout;
    int     sioFd       = -1;
    int     listenFd    = -1;
    int     nfds        = 0;
    keepGoing = 1;
    while (keepGoing) {
        /* try opening a connection to the sio_agent */
        if (sioFd < 0) {
            sioFd = tioSioSocketInit(sioPort, sioSocketPath);
            if (sioFd >= 0) {
                FD_ZERO(&currFdSet);
                FD_SET(sioFd, &currFdSet);
                nfds = max(sioFd,
                    (connectedFd >= 0) ? connectedFd : listenFd) + 1;

                /* open socket for qml viewer */
                listenFd = tioQvSocketInit(tioPort, &addressFamily,
                    tioSocketPath);
                if (listenFd < 0) {
                    /* open failed, can't continue */
                    LogMsg(LOG_ERR, "[TIO] could not open server socket\n");
                    return;
                }
                FD_SET(listenFd, &currFdSet);
                nfds = listenFd + 1;
            }
        }

        /* figure out timeout value address */
        struct timeval *pTimeout = 0;
        if (sioFd < 0) {
            /* Linux modifies the timeout value in select() so initialize it */
            timeout.tv_sec = 0;
            timeout.tv_usec = 100000;
            pTimeout = &timeout;
        }

        fd_set readFdSet = currFdSet;
        const int sel = select(nfds, &readFdSet, 0, 0, pTimeout);
        if (sel == -1) {
            if (errno != EINTR) {
                dieWithSystemMessage("select() returned -1");
            }
            /* else keepGoing was set to 0 in signal handler */
        } else if (sel > 0) {
            /* check for a new connection to accept */
            if (FD_ISSET(listenFd, &readFdSet)) {
                /* new connection is here, accept it */
                connectedFd = tioQvSocketAccept(listenFd, addressFamily);
                if (connectedFd >= 0) {
                    FD_CLR(listenFd, &currFdSet);
                    FD_SET(connectedFd, &currFdSet);
                    nfds = max(sioFd, connectedFd) + 1;
                }
            }

            /* see about auto reloading the translation file */
            if ((refreshDelay > 0) &&
                (time(0) > (lastCheckTime + refreshDelay))) {
                lastModTime = loadTranslations(translatorState, translatePath, lastModTime);
                lastCheckTime = time(0);
            }

            /* check for packet received from qml-viewer */
            if ((connectedFd >= 0) && FD_ISSET(connectedFd, &readFdSet)) {
                /* connected qml-viewer has something to say */
                char inMsg[READ_BUF_SIZE];
                const int readCount = readLine2(connectedFd, inMsg,
                    sizeof(inMsg), &fromSio, "qml-viewer");
                if (readCount < 0) {
                    /* socket closed, stop watching this file descriptor */
                    FD_CLR(connectedFd, &currFdSet);
                    FD_SET(listenFd, &currFdSet);
                    connectedFd = -1;
                    nfds = max(sioFd, listenFd) + 1;
                } else if (readCount > 0) {
                    if (sioFd >= 0) {
                        /* 
                         * this is a normal message from qml-viewer, translate
                         * it and send the result to sio_agent 
                         */ 
                        char outMsg[READ_BUF_SIZE];
                        translate_gui_msg(translatorState, inMsg, outMsg,
                            sizeof(outMsg));
                        tioSioSocketWrite(sioFd, outMsg);
                        tioSioSocketWrite(sioFd, "\r");
                    }
                }
            }

            /* check for anything from sio_agent connection */
            if ((sioFd >= 0) && FD_ISSET(sioFd, &readFdSet)) {
                /* 
                 * sio_agent socket port has something to send to the 
                 * tio_agent, if connected 
                 */
                char inMsg[READ_BUF_SIZE];
                int readCount = readLine2(sioFd, inMsg, sizeof(inMsg),
                    &fromQv, "sio-agent");
                if (readCount < 0) {
                    /* fall out of this loop to reopen connection to sio_agent */
                    FD_CLR(sioFd, &currFdSet);
                    sioFd = -1;
                    if(connectedFd >=0) {
                        close(connectedFd);
                    }
                    connectedFd = -1;
                    FD_CLR(connectedFd, &currFdSet);
                    if(listenFd >=0) {
                        close(listenFd);
                    }
                    listenFd = -1;
                    FD_CLR(listenFd, &currFdSet);
                    nfds = 0;
                } else if ((readCount > 0) && (connectedFd >= 0)) {
                    char outMsg[READ_BUF_SIZE];
                    translate_micro_msg(translatorState, inMsg, outMsg,
                        sizeof(outMsg));
                    tioQvSocketWrite(connectedFd, outMsg);
                    tioQvSocketWrite(connectedFd, "\n");
                }
            }
        } /* else timeout to retry opening sio_agent socket */
    }

    LogMsg(LOG_INFO, "[TIO] cleaning up\n");
    freeTranslations(translatorState);

    if (connectedFd >= 0) {
        close(connectedFd);
    }
    if (listenFd >= 0) {
        close(listenFd);
    }
    if (sioFd >= 0) {
        close(sioFd);
    }
    
    if (tioPort == 0) {
        /* best effort removal of socket */
        const int rv = unlink(tioSocketPath);
        if (rv == 0) {
            LogMsg(LOG_INFO, "[TIO] socket file %s unlinked\n", tioSocketPath);
        } else {
            LogMsg(LOG_INFO, "[TIO] socket file %s unlink failed\n", tioSocketPath);
        }
    }

}
예제 #10
0
/*Main Function
  Variable Definition:
  -- argc: the number of command arguments
  -- argv[]: each vairable of command arguments(argv[0] is the path of execution file forever)
  Return Value: Client exit number
*/
int main(int argc, char *argv[]){
	//Test for correct number of arguments
	if (argc != 3){
		dieWithUserMessage("Parameter(s)", "<Server Address/Name> <Server Port/Service>");
	}

	struct sigaction	handler;								//signal handler
	const char			*host = argv[1];						//first argument: host name/ip address
	const char			*service = argv[2];						//second argument: server listening port number
	int					rcvd_buffer_size = 50 * BUFFER_SIZE;	//received buffer size

	//Initialize Pinger
	initPinger();
	//Create a unreliable UDP socket
	client_socket = setupClientSocket(host, service);
	if (client_socket < 0){
		dieWithSystemMessage("setupClientSocket() failed");
	}
	//Set the received buffer size
	setsockopt(client_socket, SOL_SOCKET, SO_RCVBUF, &rcvd_buffer_size, sizeof(rcvd_buffer_size));
	//Set signal handler for alarm signal
	handler.sa_handler = catchAlarm;
	//Blocking everything in handler
	if (sigfillset(&handler.sa_mask) < 0){
		dieWithSystemMessage("sigfillset() failed");
	}
	//No flags
	handler.sa_flags = 0;
	//Set the "SIGALRM" signal
	if (sigaction(SIGALRM, &handler, 0) < 0){
		dieWithSystemMessage("sigaction() failed for SIGALRM");
	}
	//Set the "SIGINT" signal
	if (sigaction(SIGINT, &handler, 0) < 0){
		dieWithSystemMessage("sigaction() failed for SIGINT");
	}

	//Output the title
	printf("PING %s (", host);
	printSocketAddress((struct sockaddr*)address->ai_addr, stdout);
	printf(") result:\n");

	//Sleep for 1 second
	sleep(TIMEOUT);
	//Start to send ping message
	while (send_count < PING_SIZE){
		sendPingMessage();
		rcvdPingMessage(TIMEOUT);
	}
	
    
    //You should put sleep function inside the while loop and after rcvdPingMessage, and you should sleep for TIMEOUT - rtt value for this cycle #13 -4
    
    
    //Determine that no more replies that comes in
	if (send_count != rcvd_count){
		rcvdPingMessage(REPLY_TIMEOUT);
	}
	//SIGINT signal: construct ping statistics
	catchAlarm(SIGINT);
	
	return 0;
}