int main(void) { // uint8_t* udpData; uint8_t* tcpData; uint8_t p=0; uint16_t i=0; Seq_number=0xfb0983f7; Ack_number=0x00000; myport=0xb921; id=0x1229; uint8_t* http; // init controller initHw(); putsUart0("\r\nWeather forecast\r\n"); // init ethernet interface etherInit(ETHER_UNICAST | ETHER_BROADCAST | ETHER_HALFDUPLEX); etherSetIpAddress(192,168,137,199); // flash phy leds etherWritePhy(PHLCON, 0x0880); RED_LED = 1; waitMicrosecond(500000); etherWritePhy(PHLCON, 0x0990); RED_LED = 0; waitMicrosecond(500000); sendSynWeather(data); // message loop while (1) { if (etherKbhit()) { if (etherIsOverflow()) { RED_LED = 1; waitMicrosecond(100000); RED_LED = 0; } // get packet etherGetPacket(data, 1500); // handle arp request if (etherIsArp(data)) { etherSendArpResp(data); RED_LED = 1; // GREEN_LED = 1; waitMicrosecond(50000); RED_LED = 0; GREEN_LED = 0; } // handle ip datagram if (etherIsIp(data)) { if (etherIsIpUnicast(data)) { // handle icmp ping request if (etherIsPingReq(data)) { etherSendPingResp(data); GREEN_LED = 1; waitMicrosecond(50000); GREEN_LED = 0; } if(etherIsTcp(data)) { tcpData = etherGetTcpData(data); if(etherisHandshake1(data)) { etherRespondtoHandshake1(data); RED_LED = 1; //GREEN_LED=1; BLUE_LED=1; waitMicrosecond(100000); RED_LED = 0; //GREEN_LED=0; BLUE_LED=0; break; } } } } } } sendGETRequest(data); while(1) { if (etherKbhit()) { etherGetPacket(data, 1500); if(etherIsTcp(data)) { RED_LED = 1; //GREEN_LED=1; BLUE_LED=1; waitMicrosecond(100000); RED_LED = 0; //GREEN_LED=0; BLUE_LED=0; if(p<=7) { if(tcp_DataCount>0) etherRespondToData(data); } //if(p>=2) { //p=0; tcpData = etherGetTcpData(data); http=tcpData+9; if((*http==0x32))//|(*http==0x35)) { tcpData=tcpData+299; for(i=0;i<(tcp_DataCount-299);i++) { putcUart0(*tcpData); tcpData++; } if(*http==0x32) break; } //break; //sendFinRequest(data); } p++; } } } while(1); return 0; }
/** *INICIO DO PROGRAMA PRINCIPAL */ int main (int argc, char **argv) { /* Os sockets. Um que será o socket que vai escutar pelas conexões * e o outro que vai ser o socket específico de cada conexão */ int listenfd, connfd; /* Informações sobre o socket (endereço e porta) ficam nesta struct */ struct sockaddr_in servaddr; /* Retorno da função fork para saber quem é o processo filho e quem * é o processo pai */ pid_t childpid; /* Armazena linhas recebidas do cliente */ char recvline[MAXLINE + 1]; /* Armazena o tamanho da string lida do cliente */ ssize_t n; if (argc != 2) { fprintf(stderr,"Uso: %s <Porta>\n",argv[0]); fprintf(stderr,"Vai rodar um servidor HTTP <Porta> TCP\n"); exit(1); } /* Criação de um socket. Eh como se fosse um descritor de arquivo. Eh * possivel fazer operacoes como read, write e close. Neste * caso o socket criado eh um socket IPv4 (por causa do AF_INET), * que vai usar TCP (por causa do SOCK_STREAM), já que o HTTP * funciona sobre TCP, e será usado para uma aplicação convencional sobre * a Internet (por causa do número 0) */ if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket :(\n"); exit(2); } /* Agora é necessário informar os endereços associados a este * socket. É necessário informar o endereço / interface e a porta, * pois mais adiante o socket ficará esperando conexões nesta porta * e neste(s) endereços. Para isso é necessário preencher a struct * servaddr. É necessário colocar lá o tipo de socket (No nosso * caso AF_INET porque é IPv4), em qual endereço / interface serão * esperadas conexões (Neste caso em qualquer uma -- INADDR_ANY) e * qual a porta. Neste caso será a porta que foi passada como * argumento no shell (atoi(argv[1])) */ bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(atoi(argv[1])); if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { perror("bind :(\n"); exit(3); } /* Como este código é o código de um servidor, o socket será um * socket passivo. Para isto é necessário chamar a função listen * que define que este é um socket de servidor que ficará esperando * por conexões nos endereços definidos na função bind. */ if (listen(listenfd, LISTENQ) == -1) { perror("listen :(\n"); exit(4); } system("clear"); printf("[Servidor no ar. Aguardando conexoes na porta %s]\n",argv[1]); printf("[Para finalizar, pressione CTRL+c ou rode um kill ou killall]\n"); /* O servidor no final das contas é um loop infinito de espera por * conexões e processamento de cada uma individualmente */ for (;;) { /* O socket inicial que foi criado é o socket que vai aguardar * pela conexão na porta especificada. Mas pode ser que existam * diversos clientes conectando no servidor. Por isso deve-se * utilizar a função accept. Esta função vai retirar uma conexão * da fila de conexões que foram aceitas no socket listenfd e * vai criar um socket específico para esta conexão. O descritor * deste novo socket é o retorno da função accept. */ if ((connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) == -1 ) { perror("accept :(\n"); exit(5); } /* Agora o servidor precisa tratar este cliente de forma * separada. Para isto é criado um processo filho usando a * função fork. O processo vai ser uma cópia deste. Depois da * função fork, os dois processos (pai e filho) estarão no mesmo * ponto do código, mas cada um terá um PID diferente. Assim é * possível diferenciar o que cada processo terá que fazer. O * filho tem que processar a requisição do cliente. O pai tem * que voltar no loop para continuar aceitando novas conexões */ /* Se o retorno da função fork for zero, é porque está no * processo filho. */ if ( (childpid = fork()) == 0) { /**** PROCESSO FILHO ****/ printf("[Uma conexao aberta]\n"); /* Já que está no processo filho, não precisa mais do socket * listenfd. Só o processo pai precisa deste socket. */ close(listenfd); /* Agora pode ler do socket e escrever no socket. Isto tem * que ser feito em sincronia com o cliente. Não faz sentido * ler sem ter o que ler. Ou seja, neste caso está sendo * considerado que o cliente vai enviar algo para o servidor. * O servidor vai processar o que tiver sido enviado e vai * enviar uma resposta para o cliente (Que precisará estar * esperando por esta resposta) */ /* ========================================================= */ /* ========================================================= */ /* EP1 INÍCIO */ /* ========================================================= */ /* ========================================================= */ /* TODO: É esta parte do código que terá que ser modificada * para que este servidor consiga interpretar comandos HTTP */ /* Definindo o cliente */ Host cliente; cliente.destino = servaddr; cliente.socket = connfd; /* Ler a requisição do cliente*/ Request client_request = readRequest(cliente); /* Mostrar na tela as requisições dos clientes */ printf("*********************************************************************"); printf("\n [Metodo requisitado]: %s \n", client_request.metodo); printf("\n [Recurso solicitado]: %s \n", client_request.recurso); printf("\n [Protocolo]: %s \n", client_request.protocolo); /* checar a Request do client */ CR_returns returns = checkRequest(cliente, client_request); /* enviar resposta da requisição para o cliente */ if (strcmp(client_request.metodo,"GET")==0) { sendGETRequest(cliente, returns); } else if (strcmp(client_request.metodo,"POST")==0) { sendPOSTRequest(cliente, returns,client_request); } /* ========================================================= */ /* ========================================================= */ /* EP1 FIM */ /* ========================================================= */ /* ========================================================= */ /* Após ter feito toda a troca de informação com o cliente, * pode finalizar o processo filho */ printf("[Uma conexao fechada]\n"); exit(0); } /**** PROCESSO PAI ****/ /* Se for o pai, a única coisa a ser feita é fechar o socket * connfd (ele é o socket do cliente específico que será tratado * pelo processo filho) */ close(connfd); } exit(0); }