Source

oclogin / oclogin.cpp

Full commit
/*
Copyright (C) 2001-2006 Daybo Logic.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/*
  This program is a command line based simple client for OverChat,
  mainly used for beta testers and people who have very restricted
  access to a system.  It is built for UNIX and For Win32.
  Source code is not available.

  Maintainer= David Duncan Ross Palmer <daybologic.co.uk/mailddrp>
*/

#include "overchat_config.h" /* Entire project configuration */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include <string.h>
#include <signal.h>

#if defined(DAYBOTHREADS_NT)
# include <windows.h>
#elif defined(DAYBOTHREADS_PTH)
# include <pthread.h>
#else
# include <errno.h>
# include <pthread.h>
#endif /*DAYBOTHREADS_NT*/

#ifdef HDRSTOP
# pragma hdrstop
#endif

/* Disable server extensions for compile (not link though) */
#ifdef OVERCHAT_SERVER
# undef OVERCHAT_SERVER
#endif
#include "dlstdinc.h"
#include "daybothreads.h"
#include "blake.h"
#include "oclogin.h"
#include "NetBuffer.hpp"
/*-------------------------------------------------------------------------*/
#ifdef OVERCHAT_RCS_STAMPS
static const char *rcsid =
  "$Id: oclogin.cpp,v 0.5 2006/02/01 22:40:00 ddrp Exp $";
#endif /*OVERCHAT_RCS_STAMPS*/

static const char *UserName;
static const char *Password;
static char *DynServerName;

static void InstallSignals(void);
static void SigHandler(int SigNo);
static void Title(void);
static void Begin(void);
static void Error(const char* Msg);
static const char *ServerName(const char *NewName);
static void FreeServerName(void);
static void BlakeError(enum blakeError ErrorNumber);
static void OK(void);
static void BrokenPipeCallback(int Socket);
static void DataReader(int S);
static void DataWriter(
  int Socket,
  const void *RawData,
  size_t RawDataSize
);
static blake_bool_t GotChallenge(
  int Sock,
  const void *Unknown,
  const void *Nothing
);

#define GetServerName() \
          ServerName(NULL)
#define SetServerName(newname) \
          ServerName((newname))

int mymain(int argc, char* argv[]);
/*-------------------------------------------------------------------------*/
int main()
{
  /*
    This is for debugging because I don't know how to set arguments in the
    debugger
  */
  
  char* strings[] = {
    "oclogin",
    "DDRP",
    "blah",
    SERVERNAME
  };

  return mymain(sizeof(strings)/sizeof(strings[0]), strings);
}
/*-------------------------------------------------------------------------*/
int mymain(int argc, char* argv[])
{
  InstallSignals();
  Title();

  switch ( argc ) {
    case 1 : {
      Error("Nick and password not specified");
      return EXIT_FAILURE;
    }
    case 2 : {
      Error("No password!");
      return EXIT_FAILURE;
    }
    case 4 : { /* OK, we have an optional server name */
      SetServerName(argv[3]);
      /* Drop through into default */
    }
    default : {
      UserName = argv[1];
      Password = argv[2];
      SetServerName(SERVERNAME);
    }
  }

  Begin();
  FreeServerName();
  return EXIT_SUCCESS;
}
/*-------------------------------------------------------------------------*/
static void InstallSignals()
{
  #ifdef SIGPIPE
    signal(SIGPIPE, SigHandler);
  #endif /*SIGPIPE*/
  
  #ifdef SIGSEGV
    signal(SIGSEGV, SigHandler);
  #endif /*SIGSEGV*/
  
  #ifdef SIGABRT
    signal(SIGABRT, SigHandler);
  #endif /*SIGABRT*/
}
/*-------------------------------------------------------------------------*/
static void SigHandler(int SigNo)
{
  switch ( SigNo ) {
#ifdef SIGPIPE
    case SIGPIPE : {
      PostEvent(ocloginEventDisconnected);
      break;
    }
#endif /*SIGPIPE*/
    case SIGSEGV : {
      puts("Fuckin\' oclogin crashed accessing memory it didn\'t own");
      break;
    }
    case SIGABRT : {
      puts("oclogin aborted!");
      break;
    }
    default : {
      puts("An unknown signal has occurred!!!!!!");
    }
  }
  return;
}
/*-------------------------------------------------------------------------*/
static void Title()
{
  printf(
    "Overchat - oclogin console login 0.0.6\n"
    "(C)2001-2006 Daybo Logic, all rights reserved. - "
    "www.daybologic.co.uk/mailddrp\n\n"
  );
}
/*-------------------------------------------------------------------------*/
static void Begin()
{
  OVERCHAT_IP serverIP;
  enum blakeError lastError;
  TNetBuffer netbuffer(3277, false);

  puts("Beginning Login...");
  if ( !blake_Init() ) {
    Error("Can\'t initialise Blake communication library");
    return;
  }
  puts("Blake communication library stared");
  printf("Resolving %s...\n", DynServerName); 
  netbuffer.Resolve(DynServerName, &serverIP);
  if ( network_IsZeroIP(&serverIP) ) {
    Error("DNS resolution failure");
    return;
  }
  puts("Resolved");
  network_PrintIP(&serverIP);

  blake_InstallCallback(true, (WORD)bscchallenge, GotChallenge);

  printf("\nConnecting...\n");
  lastError = netbuffer.CreateSocket(NULL);
  if ( lastError == blakeSuccess ) {
    lastError = netbuffer.Connect(&serverIP);
    if ( lastError != blakeSuccess )
      BlakeError(lastError);
    else {
      printf("Connected to server\n");
      if ( !EventLoop() )
        Error("Couldn'\t initialise the event loop");
    }
  }

cleanup:
  puts("Closing connection");
  netbuffer.Close();
  puts("Shutting down communications library.");
  blake_Cleanup();
  puts("Session has terminated.");
  return;
}
/*-------------------------------------------------------------------------*/
static void Error(const char* Msg)
{
  printf("Error: %s\n", Msg);
  return;
}
/*-------------------------------------------------------------------------*/
static const char* ServerName(const char* NewName)
{
  static const char defServerName[] = "overchat"; /* DNS */

  if ( NewName ) { /* Setting a new name? */
    FreeServerName();
    DynServerName = (char*)malloc( strlen(NewName) + 1 );
    if ( DynServerName )
      strcpy(DynServerName, NewName);
  }

  if ( !DynServerName ) /* No user specified name */
    return defServerName; /* Give default */

  return DynServerName;
}
/*-------------------------------------------------------------------------*/
static void FreeServerName()
{
  if ( DynServerName )
    free(DynServerName);
}
/*-------------------------------------------------------------------------*/
static void BlakeError(enum blakeError ErrorNumber)
{
  enum blakeLang language = langEnglish;
  int len = blake_GetErrorMessage(ErrorNumber, NULL, 0, language);
  if ( len ) {
    char* msg = (char*)malloc(++len);
    if ( msg ) {
      blake_GetErrorMessage(ErrorNumber, msg, len, language);
      Error(msg);
      free(msg);
    }
  }
  return;
}
/*-------------------------------------------------------------------------*/
static void OK()
{
  puts("OK");
}
/*-------------------------------------------------------------------------*/
static void BrokenPipeCallback(int Socket)
{
  puts("You have been disconnected from the service");
  PostEvent(ocloginEventQuit);
}
/*-------------------------------------------------------------------------*/
static blake_bool_t GotChallenge(int Sock, const void* Unknown, const void* Nothing)
{
  unsigned short fakeLen = 0x1234; /* Length of imaginary packet */

  printf("Got a challenge hash from the server\n");
#if 0  
  /* Try to login */
  if ( blake_Login(Sock, UserName, Password, 0) ) {
    blake_Trace("Sent login information");
    return true;
  }
  blake_Trace("Cannot send login");
#endif

  fakeLen = network_HostToNetShort(fakeLen);
  network_Write(Sock, &fakeLen, sizeof(fakeLen)/2);
  daybothreads_Sleep(10);
  network_Write(Sock, &fakeLen+1, sizeof(fakeLen)/2);
  return false;
}
/*-------------------------------------------------------------------------*/