Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:bsrsoft
bsrsoft_ane_server_app
server.c
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File server.c of Package bsrsoft_ane_server_app
/* * Centro Universitário de Maringá * 1.° Ano - Redes de Computadores 2008 * Projeto Integrador * Alunos: * Henrique Pontalti * Jean Carlos Oliveira Guandalini * Josué Pirolo * Sérgio Roberto * * CesuRedes WebServer v1.1 * * v1.1 - Arrumado problema de acessar via telnet * */ /* Bibliotecas necessárias */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <time.h> #include <sys/stat.h>/*Utilização da struct stat para verificação de arquivos*/ #include <fcntl.h>/* Utilizado para a função open()*/ #include <sys/socket.h>/* Definicoes de sockets*/ #include <sys/wait.h>/* Biblioteca para a função waitpid() */ #include <sys/types.h>/* Tipos de socket */ #include <arpa/inet.h>/* Funcoes referentes ao inet (Rede) */ #include <unistd.h>/* Varios comandos *NIX */ /* Parametros utilizados pelo programa */ #define NOMESISVER "BSRSoft Applications Server 0.9"/* Nome do sistema */ #define PORTA (80) /* Porta utilizada pelo programa */ #define PROTOCOLO "HTTP/1.1" /* Protocolo HTTP (Versão) */ #define CONPEND (1024) /* Tamanho maximo da fila de conexoes pendentes */ #define MAXLINHA (4096) /* Tamanho de buffer */ #define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT"/*Formato de hora para cabecalho*/ /* * Variáveis globais */ // Pasta onde ficam as páginas char documentRoot[1000] = "/var/www/html"; // Resposta do servidor HTTP int reqResp = 200; // Variável para guardar o tipo de requisição(GET,POST,etc...) char tipo[10]; /* * Fim das variáveis globais */ /* * Funções variadas */ /* Função para mensagens de erro no console */ void saidaErro(char msg[100]) { fprintf(stderr, "%s: %s\r\n", NOMESISVER, msg); exit(EXIT_FAILURE); } /* Função para retornar o tipo de content-type * Retirada do site: http://www.jbox.dk/sanos/webserver.htm (SANOs Operating System) */ char *get_mime_type(char *name) { char *ext = strrchr(name, '.'); if (!ext) return NULL; if (strcmp(ext, ".html") == 0 || strcmp(ext, ".htm") == 0) return "text/html"; if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return "image/jpeg"; if (strcmp(ext, ".gif") == 0) return "image/gif"; if (strcmp(ext, ".png") == 0) return "image/png"; if (strcmp(ext, ".css") == 0) return "text/css"; if (strcmp(ext, ".au") == 0) return "audio/basic"; if (strcmp(ext, ".wav") == 0) return "audio/wav"; if (strcmp(ext, ".avi") == 0) return "video/x-msvideo"; if (strcmp(ext, ".mpeg") == 0 || strcmp(ext, ".mpg") == 0) return "video/mpeg"; if (strcmp(ext, ".mp3") == 0) return "audio/mpeg"; return NULL; } /* Função para jogar um cabeçalho padrão HTTP */ void cabecalhoPadrao(int conWebServer,char *tipoMime, int tam, time_t ultAtu) { time_t agora; char bufHora[128]; char buffer[100]; sprintf(buffer, "%s %d %s\r\n", PROTOCOLO, reqResp,tipo); write(conWebServer, buffer, strlen(buffer)); sprintf(buffer, "Server: %s\r\n", NOMESISVER); write(conWebServer, buffer, strlen(buffer)); agora = time(NULL); strftime(bufHora, sizeof(bufHora), RFC1123FMT, gmtime(&agora)); sprintf(buffer, "Date: %s\r\n", bufHora); write(conWebServer, buffer, strlen(buffer)); sprintf(buffer, "Content-Type: %s\r\n", tipoMime); write(conWebServer, buffer, strlen(buffer)); if (tam >= 0) { sprintf(buffer, "Content-Length: %d\r\n", tam); write(conWebServer, buffer, strlen(buffer)); } if (ultAtu != -1) { strftime(bufHora, sizeof(bufHora), RFC1123FMT, gmtime(&ultAtu)); sprintf(buffer, "Last-Modified: %s\r\n", bufHora); write(conWebServer, buffer, strlen(buffer)); } write(conWebServer, "\r\n", 2); } /* Função para página de erro */ int retornaErro(int conWebServer, char *mensagem) { char buffer[100]; sprintf(buffer, "<html>\n<head>\n<title>%s Erro %d</title>\n</head>\n\n", NOMESISVER,reqResp); write(conWebServer, buffer, strlen(buffer)); sprintf(buffer, "<body>\n<h1>%s Erro %d</h1>\n", NOMESISVER,reqResp); write(conWebServer, buffer, strlen(buffer)); sprintf(buffer, "<p>%s</p>\n</body>\n</html>\n",mensagem); write(conWebServer, buffer, strlen(buffer)); return 0; } /* Função para enviar o arquivo */ void enviarArquivo(int conWebServer, int recurso, char *recursoPath, struct stat *statBuffer) { char dados; int n; // Verificar se o sistema tem acesso ao arquivo FILE *arq = fopen(recursoPath, "r"); if (!arq) { reqResp = 403; sprintf(tipo, "Forbidden"); cabecalhoPadrao(conWebServer,"text/html",-1,-1); retornaErro(conWebServer,"Acesso Negado"); } else { int tamanho = S_ISREG(statBuffer->st_mode) ? statBuffer->st_size : -1; reqResp = 200; sprintf(tipo, "OK"); cabecalhoPadrao(conWebServer,get_mime_type(recursoPath),tamanho,statBuffer->st_mtime); while ((n = read(recurso, &dados,1))) { write(conWebServer, &dados, 1); } fclose(arq); } } /* Função para verificar se existe o recurso solicitado pelo browser * se tiver irá mostrar, senão retorna o erro correspondente */ void verificaRecurso(int conWebServer, char recurso[1000],char *metodo,char *ip) { char docRootLocal[MAXLINHA]; // Para concatenar com o pedido de recurso e montar a pasta inteira do site char pathbuf[MAXLINHA]; // Guardar informações sobre o caminho do recurso struct stat statBuffer; // Montar a estrutura para verificação de estado dos arquivos int len; // Para auxliar na contagem de tamanho do "caminho" int n; // Abrir o arquivo local como "inteiro" strcpy(docRootLocal,documentRoot); // Copiar para a variável docRootLocal o caminho do "Document Root" if(recurso) strcat(docRootLocal,recurso); // Concatenar com o pedido do browser else strcat(docRootLocal,"/index.html"); // Verificar o tipo de método if(strcmp(metodo, "GET") != 0) { // Método não suportado pelo servidor reqResp = 501; sprintf(tipo, "Not supported"); retornaErro(conWebServer,"Metodo nao suportado"); } else if(stat(docRootLocal, &statBuffer) == -1) { // Nessa linha verifica se o arquivo existe // Arquivo não encontrado reqResp = 404; sprintf(tipo, "Not Found"); retornaErro(conWebServer,"Pagina nao encontrada"); } // Daqui para baixo é se o arquivo for encontrado else if(S_ISDIR(statBuffer.st_mode)) { // Se não colocar a barra no final da url, no caso de ser um diretório len = strlen(docRootLocal); if (len == 0 || docRootLocal[len - 1] != '/') { // Adicionar a "/index.html" barra no final da URL(pelo menos dentro do servidor) snprintf(pathbuf, sizeof(pathbuf), "Location: %s/", docRootLocal); strcat(docRootLocal,"/index.html"); // Vai verificar se tem o index.html dentro do diretório if(stat(docRootLocal, &statBuffer) == -1) { // Arquivo não encontrado reqResp = 404; sprintf(tipo, "Not Found"); retornaErro(conWebServer,"Pagina nao encontrada"); } // Se existir o index.html, então irá mostrar else { reqResp = 200; sprintf(tipo, "OK"); n = open(docRootLocal, O_RDONLY); enviarArquivo(conWebServer,n,docRootLocal,&statBuffer); } } else { // Se não tiver colocar nada depois do nome do diretório então colocará o index.html sozinho snprintf(pathbuf, sizeof(pathbuf), "%sindex.html", docRootLocal); strcat(docRootLocal,"index.html"); if(stat(docRootLocal, &statBuffer) >= 0) { reqResp = 200; sprintf(tipo, "OK"); n = open(docRootLocal, O_RDONLY); enviarArquivo(conWebServer,n,docRootLocal,&statBuffer); } else { // Caso não existir o index.html reqResp = 404; sprintf(tipo, "Not Found"); retornaErro(conWebServer,"Pagina nao encontrada"); } } } else { // Aqui é se o browser fizer a requisição com o endereço da url completo reqResp = 200; sprintf(tipo, "OK"); n = open(docRootLocal, O_RDONLY); enviarArquivo(conWebServer,n,docRootLocal,&statBuffer); } // Jogar informações no console time_t agora = time(NULL); char bufHora[128]; strftime(bufHora, sizeof(bufHora), "%d/%b/%Y %H:%M:%S", gmtime(&agora)); printf("IP: %s [%s GMT] %s %s %s %d\n",ip, bufHora,metodo,PROTOCOLO,docRootLocal,reqResp); } /* Função para processar a requisição do browser */ void ProcessarRequisicao(int conWebServer, char ip[20]) { char linha[MAXLINHA]; char *metodo = malloc(4); char *recurso = malloc(1000); char *protocolo = malloc(20); printf("%s\n", metodo); // Jogar as informações do socket em um arquivo para pegar a requisição FILE *p = fdopen(conWebServer,"r+"); // Jogar as informações do socket na variável "linha" fgets(linha,MAXLINHA,p); // Informações pertinentes metodo = strtok(linha, " "); recurso = strtok(NULL, " "); protocolo = strtok(NULL, "\r"); /****************************************/ /* Trabalhando a requisição do cliente */ /****************************************/ // Verificar se o recurso existe verificaRecurso(conWebServer,recurso,metodo,ip); // Fechar arquivo fclose(p); } /* * Fim de funções variadas */ /* Funcao principal */ int main() { // Limpar a tela system("clear"); printf("Inicializando servidor %s...",NOMESISVER); int sWebServer, conWebServer; struct sockaddr_in serverAddr, from; /* Criar o socket * * socket(int familia, int tipo, int protocolo); * * familia = identifica o enderecamento que sera utilizado. Para IP, deve ter o valor AF_INET * tipo = Se a comunicacao sera orientada a conexao. TCP, o valor deve ser SOCK_STREAM, UDP o valor deve ser SOCK_DGRAM. * protocolo = Para a Internet, utiliza-se o valor 0(zero) * */ if((sWebServer = socket(AF_INET, SOCK_STREAM, 0)) < 0) saidaErro("Nao foi possivel criar o socket.\n"); /* Configurar a estrutura do socket * * As funcoes htonl e htons permitem a conversao de numeros inteiros longos e curtos do formato interno da maquina * para o formato utilizado na rede. * */ memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; /* Familia de procolo, nesse caso Internet */ serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* INADDR_ANY permite a recepcao em qualquer IP da maquina */ serverAddr.sin_port = htons(PORTA); /* Porta que sera feita o bind */ /* Efetuar o bind da porta no endereco IP da maquina * * bind(int socket, struct sockaddr *meuIP, int addrLen); * * socket = O descritor devolvido pela funcao socket() * O segundo parametro é um apontador para a estrutura(struct) que contem o endereço * addrLen = Tamanho da estrutura * */ if(bind(sWebServer, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) saidaErro("Nao foi possivel efetuar o bind da porta.\n"); /* Tornar o socket disponivel para conexao * * listen(int s, int backlog); * * s = Descritor do socket * backlog = Tamanho maximo da fila de conexoes pendentes * */ if(listen(sWebServer, CONPEND) < 0) saidaErro("Nao foi possivel ativar o socket.\n"); printf("[OK]\n"); memset(&from, 0, sizeof(from)); int addrlen = sizeof(from); /* * Criar um loop infinito para aguardar conexões */ while(1) { /* Aguardar conexoes */ if((conWebServer = accept(sWebServer,(struct sockaddr *)&from, &addrlen)) < 0) saidaErro("Nao foi possivel efetuar acao de accept().\n"); char ipCliente[20]; inet_ntop(AF_INET, &(from.sin_addr), ipCliente, INET_ADDRSTRLEN); // Trabalho do programa em processar as requisições ProcessarRequisicao(conWebServer,ipCliente); close(conWebServer); } }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor