Пример #1
0
// The Master Thread implements an idea of synchrony. Its task
// is to use barrier synchronization and let every thread run its
// main loop OR event loop just once before not every other thread
// has also proceeded in doing so
// this ensures the "eventually entry" of any railway API code that is 
// sequentialized due to the use of simple binary semaphore mutex
// variables
// Every thread has its own localLOCK variable, that is increased in
// every loop step, the thread must wait 
// if its own localLOCK is > 0. It is reset to 0 if ALL threads have
// set their localLOCKs to > 0 and hence have done a step
void* ThreadFunctionMaster(void* port)
{
  int track;
  while (!MasterShutdown) {
   		//do not wait for terminated threads
   			if (localTERMINATED2) {
			   localLOCK2 = 1;   
			}
  
  		//wait for all localTicks to be increased
  		if ((localLOCK2 == 1)&&(1)) {
			//fill ContactMem and OccupiedMem array
			for (track = 0; track < 48; track++) {
 			  ContactMem[track][0] = getcontact(railway,track,FIRST,1);
 			  ContactMem[track][1] = getcontact(railway,track,SECOND,1);
 			  OccupiedMem[track] = trackused(railway,track);
			}

  			//increase a tick counter (useless)
  			TICK++;
			//if (DEBUGCONTROLLER) printf("TICK %d\n",TICK);
			localLOCK2 = 0;   
  		}//end if
		usleep(1000); // sleep for 1ms
  }
  return (void *)1;
}
Пример #2
0
void GGPROTO::dccconnect(uin_t uin)
{
	struct gg_dcc *local_dcc;
	MCONTACT hContact = getcontact(uin, 0, 0, NULL);
	DWORD ip, myuin; WORD port;

	debugLogA("dccconnect(): Connecting to uin %d.", uin);

	// If unknown user or not on list ignore
	if (!hContact) return;

	// Read user IP and port
	ip = swap32(getDword(hContact, GG_KEY_CLIENTIP, 0));
	port = getWord(hContact, GG_KEY_CLIENTPORT, 0);
	myuin = getDword(GG_KEY_UIN, 0);

	// If not port nor ip nor my uin (?) specified
	if (!ip || !port || !uin) return;

	if (!(local_dcc = gg_dcc_get_file(ip, port, myuin, uin)))
		return;

	// Add client dcc to watches
	gg_EnterCriticalSection(&ft_mutex, "dccconnect", 36, "ft_mutex", 1);
	list_add(&watches, local_dcc, 0);
	gg_LeaveCriticalSection(&ft_mutex, "dccconnect", 36, 1, "ft_mutex", 1);
}
Пример #3
0
HANDLE GGPROTO::AddToList(int flags, PROTOSEARCHRESULT *psr)
{
#ifdef DEBUGMODE
	debugLogA("AddToList(): id=%s");
#endif
	GGSEARCHRESULT *sr = (GGSEARCHRESULT *)psr;
	uin_t uin;

	if (psr->cbSize == sizeof(GGSEARCHRESULT))
		uin = sr->uin;
	else
		uin = _ttoi(psr->id);

	return getcontact(uin, 1, flags & PALF_TEMPORARY ? 0 : 1, sr->nick);
}
Пример #4
0
/*
 * Get nation argument.
 * If @arg is not empty, use it.
 * Else prompt for input using @prompt.
 * If no input is provided, return -1.
 * If the argument identifies a country, return its number.  getnatp()
 * can be assumed to succeed for this number.
 * Else complain and return -1.
 * If HIDDEN is enabled, countries not contacted are not eligible
 * unless the player is a deity.
 */
int
natarg(char *arg, char *prompt)
{
    struct natstr *np = natargp(arg, prompt);
    if (!np)
	return -1;
    if (opt_HIDDEN) {
	if (!player->god && !getcontact(getnatp(player->cnum), np->nat_cnum)) {
	    if (np->nat_stat != STAT_GOD) {
		pr("Country '%s' has not been contacted.\n", arg);
		return -1;
	    }
	}
    }
    return np->nat_cnum;
}
Пример #5
0
void __cdecl GGPROTO::dccmainthread(void*)
{
	uin_t uin;
	gg_event *e;
	struct timeval tv;
	fd_set rd, wd;
	int ret;
	SOCKET maxfd;
	DWORD tick;
	list_t l;
	char szFilename[MAX_PATH];

	// Zero up lists
	watches = transfers = requests = l = NULL;

	debugLogA("dccmainthread(): started. DCC Server Thread Starting");

	// Readup number
	if (!(uin = getDword(GG_KEY_UIN, 0)))
	{
		debugLogA("dccmainthread(): No Gadu-Gadu number specified. Exiting.");
		if (hEvent) SetEvent(hEvent);
#ifdef DEBUGMODE
		debugLogA("dccmainthread(): end 1.");
#endif
		return;
	}

	// Create listen socket on config direct port
	if (!(dcc = gg_dcc_socket_create(uin, (uint16_t)getWord(GG_KEY_DIRECTPORT, GG_KEYDEF_DIRECTPORT))))
	{
		debugLogA("dccmainthread(): Cannot create DCC listen socket. Exiting.");
		// Signalize mainthread we haven't start
		if (hEvent) SetEvent(hEvent);
#ifdef DEBUGMODE
		debugLogA("dccmainthread(): end 2.");
#endif
		return;
	}

	gg_dcc_port = dcc->port;
	gg_dcc_ip = inet_addr("255.255.255.255");
	debugLogA("dccmainthread(): Listening on port %d.", gg_dcc_port);

	// Signalize mainthread we started
	if (hEvent) SetEvent(hEvent);

	// Add main dcc handler to watches
	list_add(&watches, dcc, 0);

	// Do while we are in the main server thread
	while(pth_dcc.dwThreadId && dcc)
	{
		// Timeouts
		tv.tv_sec = 1;
		tv.tv_usec = 0;

		// Prepare descriptiors for select
		FD_ZERO(&rd);
		FD_ZERO(&wd);

		for (maxfd = 0, l = watches; l; l = l->next)
		{
			gg_common *w = (gg_common*)l->data;

			if (!w || w->state == GG_STATE_ERROR || w->state == GG_STATE_IDLE || w->state == GG_STATE_DONE)
				continue;

			// Check if it's proper descriptor
			if (w->fd == -1) continue;

			if (w->fd > maxfd)
				maxfd = w->fd;
			if ((w->check & GG_CHECK_READ))
				FD_SET(w->fd, &rd);
			if ((w->check & GG_CHECK_WRITE))
				FD_SET(w->fd, &wd);
		}

		// Wait for data on selects
		ret = select(maxfd + 1, &rd, &wd, NULL, &tv);

		// Check for select error
		if (ret == -1)
		{
			if (errno == EBADF)
				debugLogA("dccmainthread(): Bad descriptor on select().");
			else if (errno != EINTR)
				debugLogA("dccmainthread(): Unknown error on select().");
			continue;
		}

		// Process watches (carefull with l)
		l = watches;
		gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
		while (l)
		{
			struct gg_common *local_c = (gg_common*)l->data;
			struct gg_dcc *local_dcc = (gg_dcc*)l->data;
			struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data;
			l = l->next;

			switch (local_c->type)
			{
				default:
					if (!local_dcc || (!FD_ISSET(local_dcc->fd, &rd) && !FD_ISSET(local_dcc->fd, &wd)))
						continue;

					/////////////////////////////////////////////////////////////////
					// Process DCC events

					// Connection broken/closed
					gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 2, "ft_mutex", 1);
					if (!(e = gg_dcc_socket_watch_fd(local_dcc)))
					{
						debugLogA("dccmainthread(): Socket closed.");
						// Remove socket and _close
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						list_remove(&watches, local_dcc, 0);
						gg_dcc_socket_free(local_dcc);

						// Check if it's main socket
						if (local_dcc == dcc) dcc = NULL;
						continue;
					} else {
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e));
					}

					switch(e->type)
					{
						// Client connected
						case GG_EVENT_DCC_NEW:
							list_add(&watches, e->event.dcc_new, 0);
							e->event.dcc_new = NULL;
							break;

						//
						case GG_EVENT_NONE:
							// If transfer in progress do status
							if (local_dcc->file_fd != -1 && local_dcc->offset > 0 && (((tick = GetTickCount()) - local_dcc->tick) > GGSTATREFRESHEVERY))
							{
								PROTOFILETRANSFERSTATUS pfts;
								local_dcc->tick = tick;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc->contact;
								pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc->file_info.size;
								pfts.totalProgress = local_dcc->offset;
								pfts.szWorkingDir = local_dcc->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc->file_info.size;
								pfts.currentFileProgress = local_dcc->offset;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 3, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							break;

						// Connection was successfuly ended
						case GG_EVENT_DCC_DONE:
							debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin);
							// Remove from watches
							list_remove(&watches, local_dcc, 0);
							// Close file & success
							if (local_dcc->file_fd != -1)
							{
								PROTOFILETRANSFERSTATUS pfts;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc->contact;
								pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc->file_info.size;
								pfts.totalProgress = local_dcc->file_info.size;
								pfts.szWorkingDir = local_dcc->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc->file_info.size;
								pfts.currentFileProgress = local_dcc->file_info.size;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 4, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
								_close(local_dcc->file_fd); local_dcc->file_fd = -1;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 5, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							// Free dcc
							gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							break;

						// Client error
						case GG_EVENT_DCC_ERROR:
							switch (e->event.dcc_error)
							{
								case GG_ERROR_DCC_HANDSHAKE:
									debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_NET:
									debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_FILE:
									debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_EOF:
									debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_REFUSED:
									debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc->peer_uin);
									break;
								default:
									debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc->peer_uin);
							}
							// Don't do anything if it's main socket
							if (local_dcc == dcc) break;

							// Remove from watches
							list_remove(&watches, local_dcc, 0);

							// Close file & fail
							if (local_dcc->contact)
							{
								_close(local_dcc->file_fd); local_dcc->file_fd = -1;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 6, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							// Free dcc
							gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							break;

						// Need file acknowledgement
						case GG_EVENT_DCC_NEED_FILE_ACK:
							debugLogA("dccmainthread(): Client: %d, File ack filename \"%s\" size %d.", local_dcc->peer_uin,
									local_dcc->file_info.filename, local_dcc->file_info.size);
							// Do not watch for transfer until user accept it
							list_remove(&watches, local_dcc, 0);
							// Add to waiting transfers
							list_add(&transfers, local_dcc, 0);

							//////////////////////////////////////////////////
							// Add file recv request
							{
								// Make new ggtransfer struct
								local_dcc->contact = (void*)getcontact(local_dcc->peer_uin, 0, 0, NULL);
								TCHAR* filenameT = mir_utf8decodeT((char*)dcc->file_info.filename);

								PROTORECVFILET pre = {0};
								pre.dwFlags = PRFF_TCHAR;
								pre.fileCount = 1;
								pre.timestamp = time(NULL);
								pre.descr.t = filenameT;
								pre.files.t = &filenameT;
								pre.lParam = (LPARAM)local_dcc;

								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 7, "ft_mutex", 1);
								ProtoChainRecvFile((UINT_PTR)local_dcc->contact, &pre);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);

								mir_free(filenameT);
							}
							break;

						// Need client accept
						case GG_EVENT_DCC_CLIENT_ACCEPT:
							debugLogA("dccmainthread(): Client: %d, Client accept.", local_dcc->peer_uin);
							// Check if user is on the list and if it is my uin
							if (getcontact(local_dcc->peer_uin, 0, 0, NULL) &&
								getDword(GG_KEY_UIN, -1) == local_dcc->uin)
								break;

							// Kill unauthorized dcc
							list_remove(&watches, dcc, 0);
							gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							break;

						// Client connected as we wished to (callback)
						case GG_EVENT_DCC_CALLBACK:
						{
							int found = 0;
							debugLogA("dccmainthread(): Callback from client %d.", local_dcc->peer_uin);
							// Seek for stored callback request
							for (l = requests; l; l = l->next)
							{
								struct gg_dcc *req = (gg_dcc*)l->data;

								if (req && req->peer_uin == local_dcc->peer_uin)
								{
									gg_dcc_set_type(local_dcc, GG_SESSION_DCC_SEND);
									found = 1;

									// Copy data req ===> dcc
									local_dcc->folder = req->folder;
									local_dcc->contact = req->contact;
									local_dcc->file_fd = req->file_fd;
									memcpy(&local_dcc->file_info, &req->file_info, sizeof(struct gg_file_info));
									// Copy data back to dcc ===> req
									memcpy(req, local_dcc, sizeof(struct gg_dcc));

									// Remove request
									list_remove(&requests, req, 0);
									// Remove dcc from watches
									list_remove(&watches, local_dcc, 0);
									// Add request to watches
									list_add(&watches, req, 0);
									// Free old dat
									gg_free_dcc(local_dcc);
									debugLogA("dccmainthread(): Found stored request to client %d, filename \"%s\" size %d, folder \"%s\".",
										req->peer_uin, req->file_info.filename, req->file_info.size, req->folder);
									break;
								}
							}

							if (!found)
							{
								debugLogA("dccmainthread(): Unknown request to client %d.", local_dcc->peer_uin);
								// Kill unauthorized dcc
								list_remove(&watches, local_dcc, 0);
								gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							}
							break;
						}
					}

					// Free event
					gg_free_event(e);
					break;

				case GG_SESSION_DCC7_SOCKET:
				case GG_SESSION_DCC7_GET:
				case GG_SESSION_DCC7_SEND:
				case GG_SESSION_DCC7_VOICE:
					if (!local_dcc7 || (!FD_ISSET(local_dcc7->fd, &rd) && !FD_ISSET(local_dcc7->fd, &wd)))
						continue;

					/////////////////////////////////////////////////////////////////
					// Process DCC7 events

					// Connection broken/closed
					gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 8, "ft_mutex", 1);
					if (!(e = gg_dcc7_watch_fd(local_dcc7)))
					{
						debugLogA("dccmainthread(): Socket closed.");
						// Remove socket and _close
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						list_remove(&watches, local_dcc7, 0);
						gg_dcc7_free(local_dcc7);
						continue;
					} else {
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e));
					}

					switch(e->type)
					{
						//
						case GG_EVENT_NONE:
							// If transfer in progress do status
							if (local_dcc7->file_fd != -1 && local_dcc7->offset > 0 && (((tick = GetTickCount()) - local_dcc7->tick) > GGSTATREFRESHEVERY))
							{
								PROTOFILETRANSFERSTATUS pfts;
								local_dcc7->tick = tick;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc7->contact;
								pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc7->size;
								pfts.totalProgress = local_dcc7->offset;
								pfts.szWorkingDir = local_dcc7->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc7->size;
								pfts.currentFileProgress = local_dcc7->offset;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 9, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							break;

						// Connection was successfuly ended
						case GG_EVENT_DCC7_DONE:
							debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin);
							// Remove from watches
							list_remove(&watches, local_dcc7, 0);
							// Close file & success
							if (local_dcc7->file_fd != -1)
							{
								PROTOFILETRANSFERSTATUS pfts;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc7->contact;
								pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc7->size;
								pfts.totalProgress = local_dcc7->size;
								pfts.szWorkingDir = local_dcc7->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc7->size;
								pfts.currentFileProgress = local_dcc7->size;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 10, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
								_close(local_dcc7->file_fd); local_dcc7->file_fd = -1;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 11, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc7, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							// Free dcc
							gg_dcc7_free(local_dcc7);
							break;

						// Client error
						case GG_EVENT_DCC7_ERROR:
							switch (e->event.dcc7_error)
							{
								case GG_ERROR_DCC7_HANDSHAKE:
									debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_NET:
									debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_FILE:
									debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_EOF:
									debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_REFUSED:
									debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_RELAY:
									debugLogA("dccmainthread(): Client: %d, Relay connection error.", local_dcc7->peer_uin);
									break;
								default:
									debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc7->peer_uin);
							}
							// Remove from watches
							list_remove(&watches, local_dcc7, 0);

							// Close file & fail
							if (local_dcc7->file_fd != -1)
							{
								_close(local_dcc7->file_fd);
								local_dcc7->file_fd = -1;
							}

							if (local_dcc7->contact) {
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 12, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc7, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}

							// Free dcc
							gg_dcc7_free(local_dcc7);
							break;
					}

					// Free event
					gg_free_event(e);
					break;
			}
		}
		gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 1, "ft_mutex", 1);
	}

	// Close all dcc client sockets
	for (l = watches; l; l = l->next)
	{
		struct gg_common *c = (gg_common*)l->data;
		if (!c) continue;
		if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET)
		{
			struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data;
			gg_dcc7_free(local_dcc7);
		}
		else
		{
			struct gg_dcc *local_dcc = (gg_dcc*)l->data;
			gg_dcc_socket_free(local_dcc);

			// Check if it's main socket
			if (local_dcc == dcc) dcc = NULL;
		}
	}
	// Close all waiting for aknowledgle transfers
	for (l = transfers; l; l = l->next)
	{
		struct gg_common *c = (gg_common*)l->data;
		if (!c) continue;
		if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET)
		{
			struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data;
			gg_dcc7_free(local_dcc7);
		}
		else
		{
			struct gg_dcc *local_dcc = (gg_dcc*)l->data;
			gg_dcc_socket_free(local_dcc);
		}
	}
	// Close all waiting dcc requests
	for (l = requests; l; l = l->next)
	{
		struct gg_dcc *local_dcc = (gg_dcc*)l->data;
		if (local_dcc) gg_free_dcc(local_dcc);
	}
	list_destroy(watches, 0);
	list_destroy(transfers, 0);
	list_destroy(requests, 0);

	gg_dcc_port = 0;
	gg_dcc_ip = 0;
	debugLogA("dccmainthread(): end. DCC Server Thread Ending");
}
Пример #6
0
////////////////////////////////////////////////////////////////////////////////
// This is main groupchat initialization routine
//
TCHAR* GGPROTO::gc_getchat(uin_t sender, uin_t *recipients, int recipients_count)
{
	list_t l;
	GGGC *chat;
	TCHAR id[32];
	uin_t uin;
	DBVARIANT dbv;
	GCDEST gcd = { m_szModuleName, 0, GC_EVENT_ADDGROUP };
	GCEVENT gce = { sizeof(gce), &gcd };

	debugLogA("gc_getchat(): Count %d.", recipients_count);
	if (!recipients) return NULL;

	// Look for existing chat
	for(l = chats; l; l = l->next)
	{
		chat = (GGGC *)l->data;
		if (!chat) continue;

		if (chat->recipients_count == recipients_count + (sender ? 1 : 0))
		{
			int i, j, found = 0, sok = (sender == 0);
			if (!sok) {
				for (i = 0; i < chat->recipients_count; i++) {
					if (sender == chat->recipients[i])
					{
						sok = 1;
						break;
					}
				}
			}
			if (sok)
				for(i = 0; i < chat->recipients_count; i++)
					for(j = 0; j < recipients_count; j++)
						if (recipients[j] == chat->recipients[i]) found++;
			// Found all recipients
			if (found == recipients_count)
			{
				if (chat->ignore)
					debugLog(_T("gc_getchat(): Ignoring existing id %s, size %d."), chat->id, chat->recipients_count);
				else
					debugLog(_T("gc_getchat(): Returning existing id %s, size %d."), chat->id, chat->recipients_count);
				return !(chat->ignore) ? chat->id : NULL;
			}
		}
	}

	// Make new uin list to chat mapping
	chat = (GGGC *)malloc(sizeof(GGGC));
	UIN2IDT(gc_id ++, chat->id);
	chat->ignore = FALSE;

	// Check groupchat policy (new) / only for incoming
	if (sender)
	{
		int unknown = (getcontact(sender, 0, 0, NULL) == NULL),
			unknownSender = unknown;
		for(int i = 0; i < recipients_count; i++)
			if (!getcontact(recipients[i], 0, 0, NULL))
				unknown ++;
		if ((getWord(GG_KEY_GC_POLICY_DEFAULT, GG_KEYDEF_GC_POLICY_DEFAULT) == 2) ||
		   (getWord(GG_KEY_GC_POLICY_TOTAL, GG_KEYDEF_GC_POLICY_TOTAL) == 2 &&
			recipients_count >= getWord(GG_KEY_GC_COUNT_TOTAL, GG_KEYDEF_GC_COUNT_TOTAL)) ||
		   (getWord(GG_KEY_GC_POLICY_UNKNOWN, GG_KEYDEF_GC_POLICY_UNKNOWN) == 2 &&
			unknown >= getWord(GG_KEY_GC_COUNT_UNKNOWN, GG_KEYDEF_GC_COUNT_UNKNOWN)))
			chat->ignore = TRUE;
		if (!chat->ignore && ((getWord(GG_KEY_GC_POLICY_DEFAULT, GG_KEYDEF_GC_POLICY_DEFAULT) == 1) ||
		   (getWord(GG_KEY_GC_POLICY_TOTAL, GG_KEYDEF_GC_POLICY_TOTAL) == 1 &&
			recipients_count >= getWord(GG_KEY_GC_COUNT_TOTAL, GG_KEYDEF_GC_COUNT_TOTAL)) ||
		   (getWord(GG_KEY_GC_POLICY_UNKNOWN, GG_KEYDEF_GC_POLICY_UNKNOWN) == 1 &&
			unknown >= getWord(GG_KEY_GC_COUNT_UNKNOWN, GG_KEYDEF_GC_COUNT_UNKNOWN))))
		{
			TCHAR *senderName = unknownSender ?
				TranslateT("Unknown") : pcli->pfnGetContactDisplayName(getcontact(sender, 0, 0, NULL), 0);
			TCHAR error[256];
			mir_sntprintf(error, TranslateT("%s has initiated conference with %d participants (%d unknowns).\nDo you want to participate?"),
				senderName, recipients_count + 1, unknown);
			chat->ignore = MessageBox(NULL, error, m_tszUserName, MB_OKCANCEL | MB_ICONEXCLAMATION) != IDOK;
		}
		if (chat->ignore)
		{
			// Copy recipient list
			chat->recipients_count = recipients_count + 1;
			chat->recipients = (uin_t *)calloc(chat->recipients_count, sizeof(uin_t));
			int i = 0;
			for(; i < recipients_count; i++)
				chat->recipients[i] = recipients[i];
			if (sender) chat->recipients[i] = sender;
			debugLog(_T("gc_getchat(): Ignoring new chat %s, count %d."), chat->id, chat->recipients_count);
			list_add(&chats, chat, 0);
			return NULL;
		}
	}

	// Create new chat window
	TCHAR status[256];
	TCHAR *senderName;
	if (sender)
	{
		senderName = pcli->pfnGetContactDisplayName(getcontact(sender, 1, 0, NULL), 0);
		mir_sntprintf(status, TranslateT("%s initiated the conference.") , senderName);
	}
	else
	{
		senderName = NULL;
		mir_sntprintf(status, TranslateT("This is my own conference."));
	}

	GCSESSION gcwindow = { sizeof(gcwindow) };
	gcwindow.iType = GCW_CHATROOM;
	gcwindow.pszModule = m_szModuleName;
	gcwindow.ptszName = sender ? senderName : TranslateT("Conference");
	gcwindow.ptszID = chat->id;
	gcwindow.dwItemData = (UINT_PTR)chat;
	gcwindow.ptszStatusbarText = status;

	// Here we put nice new hash sign
	TCHAR *name = (TCHAR*)calloc(mir_tstrlen(gcwindow.ptszName) + 2, sizeof(TCHAR));
	*name = '#'; mir_tstrcpy(name + 1, gcwindow.ptszName);
	gcwindow.ptszName = name;

	// Create new room
	if (CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM) &gcwindow)) {
		debugLog(_T("gc_getchat(): Cannot create new chat window %s."), chat->id);
		free(name);
		free(chat);
		return NULL;
	}
	free(name);

	gcd.ptszID = chat->id;
	gce.ptszUID = id;
	gce.dwFlags = GCEF_ADDTOLOG;
	gce.time = 0;

	// Add normal group
	gce.ptszStatus = TranslateT("Participants");
	CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
	gcd.iType = GC_EVENT_JOIN;

	// Add myself
	if (uin = getDword(GG_KEY_UIN, 0))
	{
		UIN2IDT(uin, id);

		TCHAR* nickT;
		if (!getTString(GG_KEY_NICK, &dbv)) {
			nickT = mir_tstrdup(dbv.ptszVal);
			db_free(&dbv);
		} else {
			nickT = mir_tstrdup(TranslateT("Me"));
		}
		gce.ptszNick = nickT;

		gce.bIsMe = 1;
		CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
		mir_free(nickT);
		debugLog(_T("gc_getchat(): Myself %s: %s (%s) to the list..."), gce.ptszUID, gce.ptszNick, gce.ptszStatus);
	}
	else debugLogA("gc_getchat(): Myself adding failed with uin %d !!!", uin);

	// Copy recipient list
	chat->recipients_count = recipients_count + (sender ? 1 : 0);
	chat->recipients = (uin_t *)calloc(chat->recipients_count, sizeof(uin_t));
	int i;
	for(i = 0; i < recipients_count; i++)
		chat->recipients[i] = recipients[i];
	if (sender) chat->recipients[i] = sender;

	// Add contacts
	for(i = 0; i < chat->recipients_count; i++) {
		MCONTACT hContact = getcontact(chat->recipients[i], 1, 0, NULL);
		UIN2IDT(chat->recipients[i], id);
		if (hContact && (name = pcli->pfnGetContactDisplayName(hContact, 0)) != NULL)
			gce.ptszNick = name;
		else
			gce.ptszNick = TranslateT("'Unknown'");
		gce.bIsMe = 0;
		gce.dwFlags = 0;
		debugLog(_T("gc_getchat(): Added %s: %s (%s) to the list..."), gce.ptszUID, gce.ptszNick, gce.ptszStatus);
		CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
	}
	gcd.iType = GC_EVENT_CONTROL;
	CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
	CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);

	debugLog(_T("gc_getchat(): Returning new chat window %s, count %d."), chat->id, chat->recipients_count);
	list_add(&chats, chat, 0);
	return chat->id;
}
Пример #7
0
int GGPROTO::gc_event(WPARAM, LPARAM lParam)
{
	GCHOOK *gch = (GCHOOK *)lParam;
	GGGC *chat = NULL;
	uin_t uin;

	// Check if we got our protocol, and fields are set
	if (!gch
		|| !gch->pDest
		|| !gch->pDest->ptszID
		|| !gch->pDest->pszModule
		|| mir_strcmpi(gch->pDest->pszModule, m_szModuleName)
		|| !(uin = getDword(GG_KEY_UIN, 0))
		|| !(chat = gc_lookup(gch->pDest->ptszID)))
		return 0;

	// Window terminated (Miranda exit)
	if (gch->pDest->iType == SESSION_TERMINATE)
	{
		debugLog(_T("gc_event(): Terminating chat %x, id %s from chat window..."), chat, gch->pDest->ptszID);
		// Destroy chat entry
		free(chat->recipients);
		list_remove(&chats, chat, 1);

		// Remove contact from contact list (duh!) should be done by chat.dll !!
		for (MCONTACT hContact = db_find_first(); hContact; ) {
			MCONTACT hNext = db_find_next(hContact);
			DBVARIANT dbv;
			if (!getTString(hContact, "ChatRoomID", &dbv)) {
				if (dbv.ptszVal && !mir_tstrcmp(gch->pDest->ptszID, dbv.ptszVal))
					CallService(MS_DB_CONTACT_DELETE, hContact, 0);
				db_free(&dbv);
			}
			hContact = hNext;
		}
		return 1;
	}

	// Message typed / send only if online
	if (isonline() && (gch->pDest->iType == GC_USER_MESSAGE) && gch->ptszText) {
		TCHAR id[32];
		UIN2IDT(uin, id);
		DBVARIANT dbv;

		GCDEST gcd = { m_szModuleName, gch->pDest->ptszID, GC_EVENT_MESSAGE };
		GCEVENT gce = { sizeof(gce), &gcd };
		gce.ptszUID = id;
		gce.ptszText = gch->ptszText;
		TCHAR* nickT;
		if (!getTString(GG_KEY_NICK, &dbv)){
			nickT = mir_tstrdup(dbv.ptszVal);
			db_free(&dbv);
		}
		else nickT = mir_tstrdup(TranslateT("Me"));
		gce.ptszNick = nickT;

		// Get rid of CRLF at back
		int lc = (int)mir_tstrlen(gch->ptszText) - 1;
		while(lc >= 0 && (gch->ptszText[lc] == '\n' || gch->ptszText[lc] == '\r'))
			gch->ptszText[lc --] = 0;

		gce.time = time(NULL);
		gce.bIsMe = 1;
		gce.dwFlags = GCEF_ADDTOLOG;
		debugLog(_T("gc_event(): Sending conference message to room %s, \"%s\"."), gch->pDest->ptszID, gch->ptszText);
		CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
		mir_free(nickT);
		
		T2Utf pszText_utf8(gch->ptszText);
		gg_EnterCriticalSection(&sess_mutex, "gc_event", 57, "sess_mutex", 1);
		gg_send_message_confer(sess, GG_CLASS_CHAT, chat->recipients_count, chat->recipients, pszText_utf8);
		gg_LeaveCriticalSection(&sess_mutex, "gc_event", 57, 1, "sess_mutex", 1);
		return 1;
	}

	// Privmessage selected
	if (gch->pDest->iType == GC_USER_PRIVMESS)
	{
		MCONTACT hContact = NULL;
		if ((uin = _ttoi(gch->ptszUID)) && (hContact = getcontact(uin, 1, 0, NULL)))
			CallService(MS_MSG_SENDMESSAGE, hContact, 0);
	}
	debugLog(_T("gc_event(): Unhandled event %d, chat %x, uin %d, text \"%s\"."), gch->pDest->iType, chat, uin, gch->ptszText);

	return 0;
}
Пример #8
0
int
news(void)
{
    struct natstr *natp;
    time_t now;
    int page;
    time_t then;
    time_t delta;
    struct nwsstr nws;
    struct nstr_item nstr;
    int page_has_news[N_MAX_PAGE + 1];
    int there_is_news = 0;
    short sectors_taken[MAXNOC][MAXNOC];
    short sectors_delta;
    short max_delta = -1;
    short abs_delta;
    short k;
    int sectors_were_taken = 0;
    natid i, j;
    char num[128];
    char *verb;

    if (!snxtitem(&nstr, EF_NEWS, "*", NULL))
	return RET_SYN;
    memset(page_has_news, 0, sizeof(page_has_news));
    memset(sectors_taken, 0, sizeof(sectors_taken));
    (void)time(&now);
    natp = getnatp(player->cnum);
    then = natp->nat_newstim;
    if (player->argp[1]) {
	/*
	 * We want to hide events before contact.  Proper solution
	 * would be to timestamp the contact.  Cheesy approximation:
	 * disable old news.
	 */
	if (opt_HIDDEN && !player->god) {
	    pr("Sorry, argument doesn't work with HIDDEN enabled\n");
	    return RET_FAIL;
	}
	delta = days(atoi(player->argp[1]));
	then = now - delta;
    }
    natp->nat_newstim = now;
    head();
    pr("\nThe details of Empire news since %s", ctime(&then));
    while (nxtitem(&nstr, &nws)) {
	if (!nws.nws_vrb || CANT_HAPPEN(nws.nws_vrb > N_MAX_VERB))
	    continue;
	if (nws.nws_when < then)
	    continue;
	if (opt_HIDDEN) {
	    if (!player->god &&
		!(getcontact(getnatp(player->cnum), nws.nws_ano) &&
		  getcontact(getnatp(player->cnum), nws.nws_vno)))
		continue;
	}
	++page_has_news[rpt[(int)nws.nws_vrb].r_newspage];
	++there_is_news;
    }
    for (page = 1; page <= N_MAX_PAGE; page++) {
	if (!page_has_news[page])
	    continue;
	pr("\n\t ===  %s  ===\n", page_headings[page].name);
	snxtitem_rewind(&nstr);
	while (nxtitem(&nstr, &nws)) {
	    if (CANT_HAPPEN(nws.nws_vrb > N_MAX_VERB))
		continue;
	    if (rpt[(int)nws.nws_vrb].r_newspage != page)
		continue;
	    if (nws.nws_when < then)
		continue;
	    if (nws.nws_ntm == 0)
		nws.nws_ntm = 1;
	    if (opt_HIDDEN) {
		if (!player->god &&
		    !(getcontact(getnatp(player->cnum), nws.nws_ano) &&
		      getcontact(getnatp(player->cnum), nws.nws_vno)))
		    continue;
	    }
	    if (page == N_FRONT &&
		(nws.nws_vrb == N_WON_SECT ||
		 nws.nws_vrb == N_AWON_SECT ||
		 nws.nws_vrb == N_PWON_SECT)) {
		sectors_taken[nws.nws_ano][nws.nws_vno] += nws.nws_ntm;
		sectors_were_taken += nws.nws_ntm;
	    }
	    preport(&nws);
	}
    }
    if (sectors_were_taken) {
	for (i = 0; i < MAXNOC; ++i) {
	    for (j = 0; j < i; ++j) {
		sectors_delta = sectors_taken[i][j] - sectors_taken[j][i];
		if (max_delta < abs(sectors_delta))
		    max_delta = abs(sectors_delta);
	    }
	}
	pr("\n\t ===  The Bottom Line   ==\n");
	for (k = max_delta; k > 0; --k) {
	    for (i = 0; i < MAXNOC; ++i) {
		for (j = 0; j < i; ++j) {
		    sectors_delta = sectors_taken[i][j] -
			sectors_taken[j][i];
		    abs_delta = abs(sectors_delta);
		    if (abs_delta != k)
			continue;
		    if (abs_delta == 1)
			verb = "stole";
		    else if (abs_delta < 4)
			verb = "took";
		    else if (abs_delta < 8)
			verb = "captured";
		    else
			verb = "seized";
		    if (sectors_delta > 0) {
			numstr(num, abs_delta);
			pr("%s %s %s sector%s from %s\n", cname(i), verb,
			   num, splur(sectors_delta), cname(j));
		    } else if (sectors_delta < 0) {
			numstr(num, abs_delta);
			pr("%s %s %s sector%s from %s\n", cname(j), verb,
			   num, splur(-sectors_delta), cname(i));
		    }
		}
	    }
	}
    }
    if (!there_is_news)
	pr("\nNo news at the moment...\n");
    return 0;
}