/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef HAVE_WINSOCK
//#define SOCKETLOG
#endif
#ifdef SOCKETLOG
#define LOG_TAG "SOCKETLOG"
#include <string.h>
#include <cutils/log.h>
#include "utils/LogSocket.h"
#include "utils/logger.h"
#include "cutils/hashmap.h"
// defined in //device/data/etc/event-log-tags
#define SOCKET_CLOSE_LOG 51000
static Hashmap* statsMap = NULL;
#define LOG_LIST_NUMBER 5
typedef struct SocketStats {
int fd;
unsigned int send;
unsigned int recv;
unsigned int ip;
unsigned short port;
short reason;
}SocketStats;
SocketStats *get_socket_stats(int fd) {
if (statsMap == NULL) {
statsMap = hashmapCreate(8, &hashmapIntHash, &hashmapIntEquals);
}
SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd);
if (s == NULL) {
// LOGD("create SocketStats for fd %d", fd);
s = (SocketStats*) malloc(sizeof(SocketStats));
memset(s, 0, sizeof(SocketStats));
s->fd = fd;
hashmapPut(statsMap, &s->fd, s);
}
return s;
}
void log_socket_connect(int fd, unsigned int ip, unsigned short port) {
// LOGD("log_socket_connect for fd %d ip %d port%d", fd, ip, port);
SocketStats *s = get_socket_stats(fd);
s->ip = ip;
s->port = port;
}
void add_send_stats(int fd, int send) {
if (send <=0) {
LOGE("add_send_stats send %d", send);
return;
}
SocketStats *s = get_socket_stats(fd);
s->send += send;
// LOGD("add_send_stats for fd %d ip %d port%d", fd, s->ip, s->port);
}
void add_recv_stats(int fd, int recv) {
if (recv <=0) {
LOGE("add_recv_stats recv %d", recv);
return;
}
SocketStats *s = get_socket_stats(fd);
s->recv += recv;
// LOGD("add_recv_stats for fd %d ip %d port%d", fd, s->ip, s->port);
}
char* put_int(char* buf, int value) {
*buf = EVENT_TYPE_INT;
buf++;
memcpy(buf, &value, sizeof(int));
return buf + sizeof(int);
}
void log_socket_close(int fd, short reason) {
if (statsMap) {
SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd);
if (s != NULL) {
if (s->send != 0 || s->recv != 0) {
s->reason = reason;
// 5 int + list type need 2 bytes
char buf[LOG_LIST_NUMBER * 5 + 2];
buf[0] = EVENT_TYPE_LIST;
buf[1] = LOG_LIST_NUMBER;
char* writePos = buf + 2;
writePos = put_int(writePos, s->send);
writePos = put_int(writePos, s->recv);
writePos = put_int(writePos, s->ip);
writePos = put_int(writePos, s->port);
writePos = put_int(writePos, s->reason);
android_bWriteLog(SOCKET_CLOSE_LOG, buf, sizeof(buf));
// LOGD("send %d recv %d reason %d", s->send, s->recv, s->reason);
}
hashmapRemove(statsMap, &s->fd);
free(s);
}
}
}
#else
void add_send_stats(int fd, int send) {}
void add_recv_stats(int fd, int recv) {}
void log_socket_close(int fd, short reason) {}
void log_socket_connect(int fd, unsigned int ip, unsigned short port) {}
#endif