Search code examples
cwinsockirc

Winsock - Why isn't ZNC (and IRC bouncer) accepting my winsock connection?


Using a typical irc client I can type in:

/server localhost 6667 nick:pass

When I enter the nick:pass I configured for ZNC,(an IRC bouncer) I'm forwarded to the server that znc is connected to under my server/nick:pass combination.

How can I programmatically open a winsock connection with all of these arguments simultaneously? /server localhost 6667 nick:pass

I've tried sending the data after connecting but znc seems to be ignoring the requests. Or I'm just not connecting to it at all. This code has connected to an IRC server that doesn't require Ping authentication, so I know it works.

#define AF_INET                    2
#define SOCK_STREAM                1
#define SOL_SOCKET                 0xffff
#define SO_SNDTIMEO                0x1005

string server_addr = "127.0.0.1";
int server_port = 6667;

void ircconnect(){
int struct_sockaddr[4];
int addr, port_low, port_high;
int opts[1];
int c;

if (irc_disabled == 1) return(0);

// fill the sockaddr struct
addr = inet_addr(server_addr);
port_low = server_port & 0x00ff;
port_high = (server_port & 0xff00) >> 8; 
struct_sockaddr[0] = AF_INET | (port_high << 16) | (port_low << 24);
struct_sockaddr[1] = addr;
struct_sockaddr[2] = 0;
struct_sockaddr[3] = 0;

// connect
s = socket(AF_INET, SOCK_STREAM, 0);

opts[0] = 1000; // send timeout milliseconds
setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, opts, 4);
c = connect(s, struct_sockaddr, 16);

Sleep(5000);

sendLine(nick + ":" + password);

Solution

  • See the python explanation below:

    int struct_sockaddr[4];
    int addr, port_low, port_high;
    int opts[1];
    int c;
    string zncauth = nick + ":" + password;
    
    if (irc_disabled == 1) return(0);
    
    // fill the sockaddr struct
    addr = inet_addr(server_addr);
    port_low = server_port & 0x00ff;
    port_high = (server_port & 0xff00) >> 8; 
    struct_sockaddr[0] = AF_INET | (port_high << 16) | (port_low << 24);
    struct_sockaddr[1] = addr;
    struct_sockaddr[2] = 0;
    struct_sockaddr[3] = 0;
    
    // connect
    s = socket(AF_INET, SOCK_STREAM, 0);
    opts[0] = 1000; // send timeout milliseconds
    setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, opts, 4);
    c = connect(s, struct_sockaddr, 16);
    
    // send
    sendLine("NICK zncbotnick");
    sendLine("USER znc bot znc :znc");
    sendLine("PASS " + zncauth);
    
    void sendLine(string text){
        if (irc_disabled == 1) return(0);
        text = text + "\r\n";
        send(s, text, StringLen(text), 0);
    }
    

    The code above finally works and this works for me in python to authenticate with ZNC. Basically, in the other language I was throwing commands to znc but they never got to znc because the code was missing return and newline characters '\r\n'. With python, I was able to diagnose the problem in real-time.

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    //Test.py
    import socket
    
    zncauth = 'nick:password'
    server_addr = '127.0.0.1'
    server_port = 6667
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((server_addr, server_port))   
    s.send( 'NICK botnick\r\n')
    s.send( 'USER znc bot znc :znc\r\n')
    s.send( 'PASS ' + zncauth + ' \r\n')