int BufferedOutputPort::send(DataBuffer* buf) {
	int toBuffer = 0;

	if (port < 0) return errorPortClosed;

	// choose buffer
	switch (policy) {
	case labeledStream:
		toBuffer = labeledStreamGetDestination(buf);
		break;
	default:
		toBuffer = 0;
		break;
	}

	// put data in port buffer
	portBuffers[toBuffer].pack(buf);

	if (portBuffers[toBuffer].getSize() > sendTreshold) {
		// buffer with enough data to be sent
		sendBufferData( &(portBuffers[toBuffer]) );
	}

	return 0;
}
int BufferedOutputPort::flush() {
	if (port < 0) return errorPortClosed;

	for (unsigned int i=0; i<portBuffers.size(); ++i) {
		sendBufferData( &(portBuffers[i]) );
	}

	return 0;
}
Exemple #3
0
/* thread for lsrp-client */
void *sockclient(void *arg){
    ThreadParam *threadParam;
    threadParam = (ThreadParam *) arg;

    int clientfd,sendbytes,recvbytes;
    struct hostent *host;
    struct sockaddr_in sockaddr;

    Router *router;
    router = threadParam->router; // get the router cfg
    getaddr(hostname, addrstr); //get hostname and ip, getaddrinfo.h
   
    /* try to get server hostname and port from the host files (.<servername>) */
    char remote_server[32];
    char portstr[6]; // to store the port
    int endsysEthx = -1; // set as iEthx if it's endsys
    char logmsg[128];
    snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): busy wait for new server starting up...\n", pthread_self());
    logging(LOGFILE, logmsg);
    while(1){
        int iEthx;
        memset(portstr, 0, sizeof(portstr)); 
        pthread_mutex_lock(&threadParam->lock_port); // Critical section to read port files
        /* Steps:
         * 1) go through all the direct_link_addr in cfg file
         * 2) if port file do NOT exists, busy wait
         * 3) if port file exists and occupied, skip it
         * 4) if port file exists and NOT occupied, use it
         * 5) update client ip into the port file
         */

        /* 1) go through all the direct_link_addr in cfg file */
        for(iEthx=0;iEthx < router->num_of_interface; iEthx++){
            if(strcmp(router->ethx[iEthx].direct_link_addr, addrstr) != 0){ // skip the local server file
                char templine[128];
                int iget;
                /* 2) if port file do NOT exists, busy wait */
                if((iget = getPort(templine, sizeof(templine), router->ethx[iEthx].direct_link_addr)) < 0 ){ // read the port file
                    continue; // if file does not exists, continue
                }
                /* 3) if port file exists and occupied, check if I'm in the list or not
                 */
                int portFound = 0;
                char tempport[6];
                if(strlen(templine) > 5){
                    char tempsplit[128];
                    strcpy(tempsplit, templine);
                    char *split1, *split2, *strsplit;
                    strsplit = tempsplit;
                    int inList = 0;
                    while(strlen(strsplit) > 0){
                        split1 = strtok_r(strsplit, ":", &split2);
                        if(strlen(split1) == 5){
                            snprintf(tempport, sizeof(tempport), "%s", split1);
                        }
                        else if(strcmp(split1, addrstr) == 0){
                            inList = 1; // in the list
                            break; // break while(strlen(strsplit) > 0)
                        }
                        strsplit = split2;
                    }

                    /* not in the list, then prepare to add me in */
                    if(inList == 0){
                        snprintf(portstr, sizeof(portstr), "%s", tempport);
                        portFound = 1;
                    }
                }
                /* 4) if port file exists and NOT occupied, use it */
                else if(strlen(templine) == 5){
                    snprintf(portstr, sizeof(portstr), "%s", templine);
                    portFound = 1;
                }

                if(portFound == 1){
                    if(router->ethx[iEthx].direct_link_type == 1){
                        endsysEthx = iEthx;
                    }
                    snprintf(remote_server, sizeof(remote_server), "%s", router->ethx[iEthx].direct_link_addr);
                    router->ethx[iEthx].direct_link_port = atoi(portstr);
                    if((host = gethostbyname(router->ethx[iEthx].direct_link_addr)) == NULL ) { // got the remote server
                        perror("gethostbyname");
                        exit(-1);
                    };
                    /* 5) update client ip into the port file, in the format:
                     *    34322:10.0.0.1:10.0.0.2
                     */
                    strcat(templine, ":");
                    strcat(templine, addrstr);
                    markPort(router->ethx[iEthx].direct_link_addr, templine); // mark that port has been used in the port file
                    snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): client %s use port %s:%s now.\n", pthread_self(), \
                                                      addrstr, router->ethx[iEthx].direct_link_addr, portstr);
                    logging(LOGFILE, logmsg);

                    /* 6) connect to remote server */
                    /*create socket*/
                    clientfd = Socket(AF_INET, SOCK_STREAM, 0);
                
                    /*parameters for sockaddr_in*/
                    sockaddr.sin_family = AF_INET;
                    sockaddr.sin_port = htons(atoi(portstr));
                    sockaddr.sin_addr = *((struct in_addr *)host->h_addr);
                    bzero(&(sockaddr.sin_zero), 8);         
                
                    /*connect to server*/
                    Connect(clientfd,sockaddr,sizeof(sockaddr));

                    break; //end the for loop
                }
            }
        }
        pthread_mutex_unlock(&threadParam->lock_port); // Critical section end
    
        sleep(READ_PORT_INTERVAL);

        if(strlen(portstr) == 5){
            break; // end the while loop
        }
        snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): No available port found, make sure all servers in direct_link_addr started.\n", pthread_self());
        logging(LOGFILE, logmsg);
        snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): wait %d seconds to try again..\n", pthread_self(), READ_PORT_INTERVAL);
        logging(LOGFILE, logmsg);
    }

    /* deal with end sys */
    if(endsysEthx != -1 ){
        int needACK;
        while(1){
            needACK = 0;
            /* read data from buffer */
            pthread_mutex_lock(&threadParam->data_buffer[endsysEthx].lock_buffer);
            if(threadParam->data_buffer[endsysEthx].buffsize > 0){
                //printf("sockclient(0x%x): threadParam->data_buffer[%d].buffsize: %d, type of the first item: %s\n", 
                //    pthread_self(), endsysEthx, threadParam->data_buffer[endsysEthx].buffsize,
                //    threadParam->data_buffer[endsysEthx].packet_q->next->packet->PacketType);

                /* out going buffer devided by interface, maybe there are other type of packet exists */
                /* do not handle ACK (110), let server side to deal with it */
                if(strcmp(threadParam->data_buffer[endsysEthx].packet_q->next->packet->PacketType, "100") == 0){
                    //snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): forward File with type %s from %s to endsystem %s through ethx %d\n",
                    printf("sockclient(0x%x): forward File with type %s from %s to endsystem %s through ethx %d\n",
                        pthread_self(), threadParam->data_buffer[endsysEthx].packet_q->next->packet->PacketType,
                        threadParam->data_buffer[endsysEthx].packet_q->next->packet->RouterID, remote_server, endsysEthx);
                    //logging(LOGFILE, logmsg);

                    sendBufferData(clientfd, &threadParam->data_buffer[endsysEthx]);

                    needACK = 1;
                }
            }
            pthread_mutex_unlock(&threadParam->data_buffer[endsysEthx].lock_buffer);

            if(needACK == 1){
                    Packet *packet_ack;
                    packet_ack= (Packet *)malloc(sizeof(Packet));

                    /* got ack from endsys for each of the packet */
                    Recv(clientfd, packet_ack, sizeof(Packet), MSG_NOSIGNAL);

                    /* only add data ack (110) to buffer */
                    if(strcmp(packet_ack->PacketType, "110") == 0){
                        // data, addBuff();
                        //Thans_Data trans_data = (Trans_Data)packet->Data;
                        //getEthx(router, trans_data.des_ip); // calculate the out interface according to the routing table
                        //snprintf(logmsg, sizeof(logmsg), "serverthread(0x%x): got ack data from %s, enqueue...\n", 
                        printf("serverthread(0x%x): got ack data from %s, enqueue...\n", 
                                 pthread_self(), packet_ack->RouterID);
                        //logging(LOGFILE, logmsg);
                        repackData(router, packet_ack);
                        pthread_mutex_lock(&threadParam->data_buffer[endsysEthx].lock_buffer);
                        addBufferData(threadParam, packet_ack);
                        pthread_mutex_unlock(&threadParam->data_buffer[endsysEthx].lock_buffer);
                    }
                    else{
                        snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): data is not ack.\n", pthread_self());
                        logging(LOGFILE, logmsg);
                    }
            }

            usleep(1); //sleep some time for lock relase
        }
    }
    /* other routers */
    else{

        /* there are 5 types of Neighbor Acquisition Packets.
         * neighbor Acquisition Type:
         * neighbor_req: Be_Neighbors_Request(000) or Cease_Neighbors_Request(100)
         * neighbor_reply: Be_Neighbors_Confirm(101), Be_Neighbors_Refuse(111),
         *                 or Cease_Neighbors_Confirm(101)   */
        Packet *neighbor_req, *neighbor_reply;
    
        /* generate neighbors_req according to configure file */
        neighbor_req = genNeighborReq(router, atoi(portstr)); // msg to be sent out
        send(clientfd, neighbor_req, sizeof(Packet), MSG_NOSIGNAL);
    
        neighbor_reply = (Packet *)malloc(sizeof(Packet));
        /* Receive neighbors_reply from remote side */
        Recv(clientfd, neighbor_reply, sizeof(Packet), MSG_NOSIGNAL);
    
        if(strcmp(neighbor_reply->Data.NeighborAcqType, "001") == 0){
    
            int hello_interval = router->hello_interval;
            int ping_interval = router->ping_interval;
            int ls_updated_interval = router->ls_updated_interval;
    
            int hello_sent = 0, ping_sent = 0, lsa_sent = 0;
            time_t now1, now2, now3;
            int ls_sequence_number = 0;
    
            struct timeval timer; // use high quality timer to calculate the ping cost
            struct timezone tzp;
    
            int ethx = getEthx(router, remote_server);
            Packet *packet_req, *packet_reply; // MUST use pointer to fit different Packet
    
            while(1){
    
                gettimeofday(&timer, &tzp);
                time_t now = timer.tv_sec;
    
                /* read data from buffer */
                if(threadParam->data_buffer[ethx].buffsize > 0){
                    snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): threadParam->data_buffer[%d].buffsize: %d, first item type %s\n", 
                            pthread_self(), ethx, threadParam->data_buffer[ethx].buffsize, 
                            threadParam->data_buffer[ethx].packet_q->next->packet->PacketType);
                    logging(LOGFILE, logmsg);
    
                    /* Data or ACK packet */
                    if(strcmp(threadParam->data_buffer[ethx].packet_q->next->packet->PacketType, "100") == 0 ||
                            strcmp(threadParam->data_buffer[ethx].packet_q->next->packet->PacketType, "110") == 0){
                        //snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): forward Data %s packet to %s\n", 
                        printf("sockclient(0x%x): forward Data %s packet to %s\n", 
                                pthread_self(), threadParam->data_buffer[ethx].packet_q->next->packet->RouterID, remote_server);
                        //logging(LOGFILE, logmsg);
                        pthread_mutex_lock(&threadParam->data_buffer[ethx].lock_buffer);
                        sendBufferData(clientfd, &threadParam->data_buffer[ethx]);
                        pthread_mutex_unlock(&threadParam->data_buffer[ethx].lock_buffer);
                    }
    
                }

                if(threadParam->lsa_buffer[ethx].buffsize > 0){
                    snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): threadParam->lsa_buffer[%d].buffsize: %d, first item type %s\n",
                            pthread_self(), ethx, threadParam->lsa_buffer[ethx].buffsize,
                            threadParam->lsa_buffer[ethx].packet_q->next->packet->PacketType);
                    logging(LOGFILE, logmsg);

                    /* LSA packet */
                    if(strcmp(threadParam->lsa_buffer[ethx].packet_q->next->packet->PacketType, "010") == 0){
                        snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): forward LSA %s packet to %s\n",
                                pthread_self(), threadParam->lsa_buffer[ethx].packet_q->next->packet->RouterID, remote_server);
                        logging(LOGFILE, logmsg);
                        pthread_mutex_lock(&threadParam->lsa_buffer[ethx].lock_buffer);
                        sendBufferLSA(clientfd, &threadParam->lsa_buffer[ethx]);
                        pthread_mutex_unlock(&threadParam->lsa_buffer[ethx].lock_buffer);
                    }
                }


                /* sending other packet */
                /* hello message */
                if(now % hello_interval ==0){
                    if(hello_sent == 0){
                        now1 = now;
                        hello_sent = 1;
        
                        pthread_mutex_lock(&threadParam->lock_send); // Critical section to read port files
                        sendHello(clientfd, router, atoi(portstr));
                        pthread_mutex_unlock(&threadParam->lock_send); // Critical section end
    
                        snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): Hello packet sent.\n", pthread_self());
                        logging(LOGFILE, logmsg);
                    }
                    if(now != now1){
                        hello_sent = 0;
                    }
                }
                /* ping message */
                if(now % ping_interval ==0){
                    if(ping_sent == 0){
                        now1 = now;
                        ping_sent = 1;
        
                        pthread_mutex_lock(&threadParam->lock_send); // Critical section to read port files
                        sendPing(clientfd, router, timer, ethx);
                        pthread_mutex_unlock(&threadParam->lock_send); // Critical section end
    
                        snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): Ping packet sent.\n", pthread_self());
                        logging(LOGFILE, logmsg);
                    }
                    if(now != now1){
                        ping_sent = 0;
                    }
                }
                /* lsa message */
                if(now % ls_updated_interval ==0){
                    if(lsa_sent == 0){
                        now2 = now;
                        lsa_sent = 1;
                        ls_sequence_number++;
    
                        /* TODO: check acknowledgment, keep sending if no ack */
                        pthread_mutex_lock(&threadParam->lock_send); // Critical section to read port files
                        //printf("sockclient(0x%x): send LSA packet from %s to %s\n", pthread_self(), addrstr, remote_server);
                        sendNewLSA(clientfd, threadParam, ls_sequence_number, timer);
                        pthread_mutex_unlock(&threadParam->lock_send); // Critical section end
                        snprintf(logmsg, sizeof(logmsg), "sockclient(0x%x): LSA packet sent.\n", pthread_self());
                        logging(LOGFILE, logmsg);
                    }
                    if(now != now2){
                        lsa_sent = 0;
                    }
                }
    
                usleep(1); //sleep some time for lock relase
     
            } //endof while(1)
    
        } // endof if(strcmp(neighbor_reply
    } // endof if endsysEthx

    close(clientfd);
    pthread_exit(0);
}