[FUG-BR] Fwd: "Clonar" conexão

Otacílio otacilio.neto em bsd.com.br
Seg Jun 19 15:23:09 BRT 2017


Em 19/06/2017 09:59, Renato Frederick escreveu:
> Em 19 de junho de 2017 09:27, Otacílio <otacilio.neto em bsd.com.br 
> <mailto:otacilio.neto em bsd.com.br>> escreveu:
>
>     Em 19/06/2017 07:45, Renato Frederick escreveu:
>>
>>
>>
>     A comunicação é feita por TCP ou UDP?
>
>     []'s
>
>     -Otacílio
>
>
> Olá Otacílio! É TCP.
>
> Explicando melhor: O que acontece é que eu tenho um GPS na moto e ele 
> envia atualização para um servidor web que montei(ao invés de usar 
> estes da china que não tem muito recurso, ou pagar 20 a 30 reais nos 
> brasileiros). Lá mostra meu histórico, define cercas(entrou ou saiu do 
> espaço definido manda SMS/email), etc.
>
> Porém no GPS eu envio um comando indicando IP e porta do servidor que 
> ele vai usar. não posso usar DNS porque a maioria das telemetria não 
> manda DNS direito ou o meu GPS não entende.
>
> E eu sempre estou desenvolvendo e melhorando o software, fazendo isto 
> na máquina de casa, que tem IP ADSL dinâmico.
>
> Não quero tirar o GPS de usar o IP de producao e colocar em testes, 
> pois às vezes o gps fica meio doido, tem que dar reset, quero mexer 
> nele menos possível, até porque quanto menos eu mexer melhor, pois em 
> uma emergência eu preciso ter na hora a localização, depois que eu 
> bloquear a moto, já que muitos meliantes são tão tranquilos que mesmo 
> bloqueado abrem o banco e começam a procurar, então tempo é importante.
>
> Então eu queria colocar no GPS o IP fixo que já tenho a produção, 
> porém em outra porta(1234) e daí nesta porta usar o NETCAT que vai 
> jogar a string(dados hexadecimais reportando longitude + hora/data) 
> para a produção na porta certa(5023) e também lá em casa na mesma porta.
>
> Assim, eu tenho garantia que tudo que ele registrar em um tem que 
> aparecer no outro. Se não acontecer é que algo no programa está 
> errado, pode ser algo que eu fiz.
> Obrigado!
>

Escrevi este pequeno programa que quebra o seu galho.

Ele conecta no servidor de produção e espera a conexão do GPS e de um 
cliente espião. Tudo o que o GPS enviar ele vai enviar para o servidor 
de produção e para o cliente espião. Tudo o que o servidor ou o cliente 
enviar ele vai encaminhar para o GPS. É muito fácil de usar. Qualquer 
coisa entre em contato.

[]'s
-Otacílio

/**
  * Copyright(C) Otacílio de Araújo Ramos Neto
  * Você pode fazer o que quiser com este software, exceto mudar esta 
licença e/ou dizer que foi você
  * quem escreveu.
  *
  * Este software é distribuído acreditando-se que está correto e é 
totalmente funcional, mas sem
  * nenhuma garantia disso ou de que é adequado a um determinado fim. 
Use-o sob sua conta e risco.
  *
  * Para compilar use: cc -Wall -O2 -pipe -o gpsc gpsc.c  -lpthread
  */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <getopt.h>             /* getopt_long() */

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define BUFFER_SIZE 4*1024
#define BACKLOG 4

const char short_options[] = "s:p:l:c:";

const struct option
long_options[] = {
     { "server",  required_argument, NULL, 's' },
     { "port",    required_argument, NULL, 'p' },
     { "ouca",  required_argument, NULL,   'l' },
     { "client",  required_argument, NULL, 'c' },
     { 0,          0,                  0,       0  }
};

void help(char *nome);
int conectaServidorProducao(char *server, char *porta);
void *servidorProducao(void *p);
void *servidorCliente(void *p);
void *servidorGPS(void *p);
void sigpipe(int i);

char server[1024]="\0";
char porta[6]="\0";
char ouca[6]="\0";
char client[6]="\0";
int producaoSocket=-1;
int gpsSocket=-1;
int clienteSocket=-1;

int main(int argc, char **argv){
     pthread_t produServer, clienteServer, gpsServer;
     for (;;) {
         int idx;
         int c;

         c = getopt_long(argc, argv, short_options, long_options, &idx);

         if (-1 == c)
             break;

         switch (c) {
         case 0: // getopt_long() flag
             break;
         case 's':
             strncpy(server, optarg, sizeof(server));
             server[sizeof(server)-1] = '\0';
             break;
         case 'p':
             strncpy(porta, optarg, sizeof(porta));
             porta[sizeof(porta)-1] = '\0';
             break;
         case 'l':
             strncpy(ouca, optarg, sizeof(ouca));
             ouca[sizeof(ouca)-1] = '\0';
             break;
         case 'c':
             strncpy(client, optarg, sizeof(client));
             client[sizeof(client)-1] = '\0';
             break;
         default:
             help(argv[0]);
             exit(EXIT_FAILURE);
         }
     }

     if(!strlen(server)){
         fprintf(stderr, "Voce precisa informar o endereço do servidor 
de produção\n\n");
         help(argv[0]);
         exit(EXIT_FAILURE);
     }

     if(!strlen(porta)){
         fprintf(stderr, "Voce precisa informar a porta do servidor de 
produção\n\n");
         help(argv[0]);
         exit(EXIT_FAILURE);
     }

     if(!strlen(ouca)){
         fprintf(stderr, "Voce precisa informar a porta que deve ouvir o 
GPS\n\n");
         help(argv[0]);
         exit(EXIT_FAILURE);
     }

     if(!strlen(client)){
         fprintf(stderr, "Voce precisa informar a porta que o cliente 
vai conectar\n\n");
         help(argv[0]);
         exit(EXIT_FAILURE);
     }

     signal(SIGPIPE, sigpipe);

     // Cria o thread responsável por conectar no servidor de produção
     if (pthread_create(&produServer, NULL, servidorProducao, NULL)) {
         fprintf(stderr,"Erro ao criar o thread para comunicação com o 
servidorde produção.\n");
         exit(EXIT_FAILURE);
     }
     // Cria o thread responsável por ouvir o cliente
     if(pthread_create(&clienteServer, NULL, servidorCliente, NULL)){
         fprintf(stderr, "Erro ao criar o thread para comunicação com o 
cliente espição.\n");
         exit(EXIT_FAILURE);
     }
     // Cria o thread responsável por ouvir o GPS
     if(pthread_create(&gpsServer, NULL, servidorGPS, NULL)){
         fprintf(stderr, "Erro ao criar o thread para comunicação com o 
cliente GPS.\n");
         exit(EXIT_FAILURE);
     }

     pthread_join(produServer, NULL);
     pthread_join(clienteServer, NULL);
     pthread_join(gpsServer, NULL);

     printf("DEBUG\n");
     return 0;
}

void help(char *nome)
{
     fprintf(stderr,     "Voce deve usar: %s <options>\n"
     "-s | --server nome de host         Nome de host do servidor de 
produção\n"
     "-p | --port   porta no servidor    Porta do servidor de produção\n"
     "-l | --ouca   porta do GPS         Porta em que o GPS vai conectar\n"
     "-c | --client porta do cliente     Porta em que o cliente espião 
vai conectar\n", nome);
}

void sigpipe(int i)
{
     fprintf(stderr, "broken pipe\n");
}

int conectaServidorProducao(char *server, char *porta)
{
     struct addrinfo hints, *result = NULL, *ptr = NULL;
     int iResult;
     int producaoSocket=-1;

     bzero(&hints, sizeof(hints));

     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_protocol = IPPROTO_TCP;

     // Resolve the server address and port
     iResult = getaddrinfo(server, porta, &hints, &result);
     if ( iResult != 0 ) {
         printf("getaddrinfo failed with error: %d\n", iResult);
         exit(EXIT_FAILURE);
     }

     // Attempt to connect to an address until one succeeds
     for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

         // Create a SOCKET for connecting to server
         producaoSocket = socket(ptr->ai_family, ptr->ai_socktype, 
ptr->ai_protocol);
         if (producaoSocket < 0){
             perror("socket");
             exit(EXIT_FAILURE);
         }

         // Connect to server.
         iResult = connect( producaoSocket, ptr->ai_addr, 
(int)ptr->ai_addrlen);
         if (iResult == -1) {
             close(producaoSocket);
             producaoSocket = -1;
             continue;
         }

         break;
     }

     freeaddrinfo(result);

     if (producaoSocket == -1) {
            printf("Unable to connect to server %s:%s!\n", server, porta);
     }

     return producaoSocket;
}


int preparaConexao(uint16_t porta)
{
     int s;
     int optval;
     struct sockaddr_in sa;

     if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
         perror("Nao foi possivel criar o socket servidor");
         exit(EXIT_FAILURE);
     }

     bzero(&sa, sizeof(sa));

     sa.sin_family = AF_INET;
     sa.sin_port   = htons(porta);

     if (INADDR_ANY)
         sa.sin_addr.s_addr = htonl(INADDR_ANY);

     // Configura o socket para reutilizar um endereço
     optval = 1;
     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);

     if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
         perror("Erro ao fazer o bind para o socket do cliente");
         exit(EXIT_FAILURE);
     }

     listen(s, BACKLOG);

     return s;
}

void *servidorCliente(void *p)
{
     int socket;
     socklen_t b;
     struct sockaddr_in sa;
     char buffer[BUFFER_SIZE];
     int lgpsSocket=-1;
     ssize_t nbytes;
     uint16_t porta = (int)strtol(client, (char **)NULL, 10);

     socket = preparaConexao(porta);

     b = sizeof(sa);

     for(;;){
         if ((clienteSocket = accept(socket, (struct sockaddr *)&sa, 
&b)) < 0) {
             perror("(servidorClient) Erro na chamada accept");
             exit(EXIT_FAILURE);
         }

         printf("(servidorClient) cliente conectado\n");
         if(clienteSocket!=-1){
             do{
                 // Vamos esperar alguma coisa do servidor. Se chegar 
escreve no socket do GPS
                 nbytes = read(clienteSocket, buffer, sizeof(buffer));

                 if(lgpsSocket==-1 && gpsSocket!=-1)
                     if((lgpsSocket = dup(gpsSocket))==-1){
                     perror("(servidorCliente) Erro ao executar 
lgpsSocket = dup(gpsSocket)");
                     exit(EXIT_FAILURE);
                 }

                 if(nbytes>0){
                     if(lgpsSocket!=-1){
                         // Escreve a tralha do lado do GPS
                         if(write(lgpsSocket, buffer, nbytes) != nbytes){
                             fprintf(stderr, "(servidorClient) Pacote 
perdido, numero de bytes escritos no GPS diferente do lido do cliente\n");
                             lgpsSocket = -1;
                         }
                     }else if(lgpsSocket==-1){
                         fprintf(stderr, "(servidorClient) Pacote 
perdido, GPS socket fechado\n");
                     }else{
                         fprintf(stderr, "(servidorClient) Conexao 
fechada, nbytes = %zd\n", nbytes);
                     }
                 }else if(nbytes==0){
                     fprintf(stderr, "(servidorClient) Socket fechado\n");
                 }
             }while(nbytes>0);
             close(clienteSocket);
         }
         sleep(3);
     }

     return NULL;
}

void *servidorGPS(void *p)
{
     int socket;
     socklen_t b;
     struct sockaddr_in sa;
     char buffer[BUFFER_SIZE];
     int lproducaoSocket=-1;
     int lclienteSocket=-1;
     ssize_t nbytes;
     uint16_t porta = (int)strtol(ouca, (char **)NULL, 10);

     socket = preparaConexao(porta);

     b = sizeof(sa);

     for(;;){
         if ((gpsSocket = accept(socket, (struct sockaddr *)&sa, &b)) < 0) {
             perror("(servidorGPS) Erro na chamada accept");
             exit(EXIT_FAILURE);
         }
         printf("(servidorGPS) GPS conectado\n");
         if(gpsSocket!=-1){
             do{
                 // Vamos esperar alguma coisa do servidor. Se chegar 
escreve no socket do GPS
                 nbytes = read(gpsSocket, buffer, sizeof(buffer));

                 if(producaoSocket!=-1 && lproducaoSocket==-1){
                     if((lproducaoSocket=dup(producaoSocket))==-1){
                         perror("(servidorGPS) Erro ao executar 
lproducaoSocket=dup(producaoSocket)");
                         exit(EXIT_FAILURE);
                     }
                 }
                 if(clienteSocket!=-1 && lclienteSocket==-1){
                     if((lclienteSocket=dup(clienteSocket))==-1){
                         perror("(servidorGPS) Erro ao executar 
lclienteSocket=dup(clienteSocket)");
                         exit(EXIT_FAILURE);
                     }
                 }

                 if(nbytes>0){
                     if(lproducaoSocket!=-1){
                         // Escreve a tralha do lado do servidor
                         if(lproducaoSocket!=-1 && 
write(lproducaoSocket, buffer, nbytes) != nbytes){
                             fprintf(stderr, "(servidorGPS) Pacote 
perdido, numero de bytes escritos no servidor de producao diferente do 
lido do GPS\n");
                             lproducaoSocket = -1;
                         }
                         if(lclienteSocket!=-1 && write(lclienteSocket, 
buffer, nbytes) != nbytes){
                             fprintf(stderr, "(servidorGPS) Pacote 
perdido, numero de bytes escritos no cliente diferente do lido do GPS\n");
                             lclienteSocket = -1;
                         }
                     }else if(lproducaoSocket==-1){
                         fprintf(stderr, "(servidorGPS) Pacote perdido, 
producao socket fechado\n");
                     }else{
                         fprintf(stderr, "(servidorGPS) Conexao fechada, 
nbytes = %zd\n", nbytes);
                     }
                 }else if(nbytes==0){
                     fprintf(stderr, "(servidorGPS) Socket do GPS 
fechado\n");
                 }
             }while(nbytes>0);
             close(gpsSocket);
         }
         sleep(3);
     }

     return NULL;
}

void *servidorProducao(void *p)
{
     char buffer[BUFFER_SIZE];
     int lgpsSocket=-1;
     ssize_t nbytes;
     for(;;){
         producaoSocket=conectaServidorProducao(server, porta);
         if(producaoSocket!=-1){
             printf("(servidorProducao) Conectado em %s:%s\n", server, 
porta);
             do{
                 // Vamos esperar alguma coisa do servidor. Se chegar 
escreve no socket do GPS
                 nbytes = read(producaoSocket, buffer, sizeof(buffer));
                 if(lgpsSocket==-1 && gpsSocket!=-1){
                     if((lgpsSocket=dup(gpsSocket))==-1){
                         perror("(servidorProducao) Erro ao executar 
lgpsSocket=dup(gpsSocket)");
                         exit(EXIT_FAILURE);
                     }
                 }

                 if(nbytes>0){
                     if(lgpsSocket != -1){
                         // Escreve a tralha do lado do GPS
                         if(write(lgpsSocket, buffer, nbytes) != nbytes){
                             fprintf(stderr, "(servidorProducao) Pacote 
perdido, numero de bytes escritos no GPS diferente do lido do servidor 
de producao\n");
                             lgpsSocket = -1;
                         }
                     }else if(lgpsSocket==-1){
                         fprintf(stderr, "(servidorProducao) Pacote 
perdido, GPS socket fechado\n");
                     }else{
                         fprintf(stderr, "(servidorProducao) Conexao 
fechada, nbytes = %zd\n", nbytes);
                     }
                 }else if(nbytes==0){
                     fprintf(stderr, "(servidorProducao) Socket fechado\n");
                 }
             }while(nbytes>0);
             close(producaoSocket);
         }
         sleep(3);
     }

     // Chega nunca aqui
     return NULL;
}



Mais detalhes sobre a lista de discussão freebsd