Come manipolare il flusso di pacchetti in un proxy TCP

1

Sto testando sul mio laptop un proxy TCP C ++ in ascolto su una porta fissa data alla riga di comando; il proxy funziona con il solito bind e listen e cicli su connessioni in entrata con accept , forking per ogni connessione accettata. Le richieste GET e CONNECT sono gestite.

Ora sto pianificando di consegnare i pacchetti non come vengono, ma seguendo una priorità: alcune connessioni, quindi alcuni pacchetti, hanno priorità più alta e devono essere consegnate prima di altre. La priorità è determinata guardando il campo Host nel primo pacchetto inviato dal client, quello contenente la richiesta GET o CONNECT.

I pacchetti vengono inseriti e rimossi in quattro deque , uno per ogni livello di priorità: i pacchetti vengono inseriti negli spazi aggiuntivi corrispondenti in base alle loro priorità e vengono rimossi dalle cariche più elevate (priorità più alte).

Gli elementi memorizzati in deque , che rappresentano un singolo pacchetto, sono personalizzati struct :

typedef struct infoPacket {
    // client and server socket descriptors for send() and recv() 
    int clientFd;
    int serverFd;
    // 0 = GET, 1 = CONNECT
    int request;
    // 0 = DIRECTION_UPLOAD, 1 = DIRECTION_DOWNLOAD
    int direction;
    int priority;
    // actual data
    std::string payload;
    int payloadSize;
    in_addr_t serveraddr;
    std::string host;
    std::chrono::time_point<std::chrono::system_clock> start;
} infoPkt;

La questione è che ho un problema di progettazione: mentre un proxy normale gestiva le connessioni in entrata eseguendo la forking e lasciando che il figlio gestisse il flusso dei pacchetti, ora devo ricevere manualmente un pacchetto da entrambi i lati delle connessioni, controllare il pacchetto priorità, mettilo nell'abbinamento deque mentre rimuovo un pacchetto da deque , vedi a quale connessione appartiene e invialo alla sua destinazione ... per tutti i pacchetti di tutte le connessioni.

Se continuo a biforcarsi per gestire ogni connessione, ci deve essere una sorta di IPC poiché il processo principale è dove vengono memorizzati i deque s che contengono i pacchetti (i pacchetti saranno inseriti dai bambini e rimossi per essere usati dai bambini ) mentre i processi figli sono dove le connessioni sono attive (i pacchetti saranno inviati a deque quando ricevuti e alle loro destinazioni quando rimossi da deque ).

Potrei non occuparmi di questo biforcarsi e tenere un elenco di coppie di descrittori di socket per ogni connessione, un thread di inserimento sarà select o poll per controllare i descrittori di file socket socket disponibili e inserire i pacchetti in deque , mentre un thread di rimozione prenderà pacchetti da deque e li invierà alla loro destinazione. Ma, se ricordo bene, la coppia non è un modo corretto per identificare una connessione.

Il meccanismo di priorità

deque è fatto: ciò che mi confonde è il numero di coppie di socket e il modo in cui recv da e send a loro.

Qualche consiglio su come affrontarlo?

Lavorare su Ubuntu x86_64.

    
posta elmazzun 28.09.2016 - 13:37
fonte

2 risposte

2

... the pair is not a proper way to identify a connection

va bene: finché riesci a capire quando stai ricevendo su qualche socket, su quale altro socket devi inoltrare, hai tutto ciò che ti serve.

Poiché i socket sono rappresentati da numeri interi, è facile mantenere un map<int,int> o unordered_map<int,int> che memorizza sia source- > dest che dest- > source per ricerche facili.

In pratica, accetterai alcune connessioni in entrata, fornirai un singolo socket (sorgente), quindi creerai la connessione in uscita correlata, fornirai un altro socket (di destinazione) e quindi avrai una coppia di socket. Aggiungili entrambi alla / e tua ricerca / e alla selezione / poll fd set per la lettura, e sei a posto.

Se stai mantenendo questo single-thread, assicurati di usare I / O non bloccante su entrambi i socket. Devi tenere traccia delle scritture non completate, ma le tue code prioritarie ti aiuteranno comunque.

    
risposta data 28.09.2016 - 14:08
fonte
1

Potresti considerare di lasciare che lo stack di rete gestisca la maggior parte di ciò per te.

Puoi utilizzare setsockopt ( SO_PRIORITY ,...) per impostare le priorità sui socket in uscita. Lo stack del protocollo ordinerà quindi i pacchetti in base alla priorità assegnata a ciascun socket.

Questo dovrebbe permetterti di mantenere l'architettura esistente con poche o nessuna modifica dato che non devi ritirare i pacchetti in un unico posto per prioritarli.

    
risposta data 30.09.2016 - 08:42
fonte

Leggi altre domande sui tag