软总线源码分析8:传输模块
前面我们看过了软总线的发现,组网,认证处理,现在我们看一下软总线的传输处理。
创建会话
创建会话的接口如下:
SoftBusServer::CreateSessionServer(const char *pkgName, const char *sessionName)
其直接调用了函数TransCreateSessionServer,其源码如下:
int32_t TransCreateSessionServer(const char *pkgName, const char *sessionName){ if (!IsValidString(pkgName, PKG_NAME_SIZE_MAX) || !IsValidString(sessionName, SESSION_NAME_SIZE_MAX)) { return SOFTBUS_INVALID_PARAM; } if (CheckTransPermission(sessionName, pkgName, ACTION_CREATE) pkgName, sizeof(newNode->pkgName), pkgName) != EOK) { SoftBusFree(newNode); return SOFTBUS_ERR; } if (strcpy_s(newNode->sessionName, sizeof(newNode->sessionName), sessionName) != EOK) { SoftBusFree(newNode); return SOFTBUS_ERR; } newNode->type = SEC_TYPE_CIPHERTEXT; int ret = TransSessionServerAddItem(newNode); if (ret != SOFTBUS_OK) { SoftBusFree(newNode); if (ret == SOFTBUS_SERVER_NAME_REPEATED) { LOG_INFO("SessionServer is already created [%s]", sessionName); return SOFTBUS_SERVER_NAME_REPEATED; } return ret; } LOG_INFO("CreateSessionServer OK, pkg name: [%s], session name: [%s]", pkgName, sessionName); return SOFTBUS_OK;}
该函数首限创建了一个SessionServer节点,然后将其加入到g_sessionServerList列表中。
打开会话
打开会话的接口如下:
int32_t SoftBusServer::OpenSession(const char *mySessionName, const char *peerSessionName, const char *peerDeviceId, const char *groupId, int32_t flags)
其调用了函数TransOpenSession,源码如下:
int32_t TransOpenSession(const char *mySessionName, const char *peerSessionName, const char *peerDeviceId, const char *groupId, int32_t flags){ LOG_INFO("trans server opensession."); if (!IsValidString(mySessionName, SESSION_NAME_SIZE_MAX) || !IsValidString(peerSessionName, SESSION_NAME_SIZE_MAX) || !IsValidString(peerDeviceId, DEVICE_ID_SIZE_MAX) || !IsValidString(groupId, GROUP_ID_SIZE_MAX)) { return INVALID_CHANNEL_ID; } char pkgName[PKG_NAME_SIZE_MAX]; if (TransGetPkgNameBySessionName(mySessionName, pkgName, PKG_NAME_SIZE_MAX) != SOFTBUS_OK) { LOG_ERR("TransGetPkgNameBySessionName failed"); return SOFTBUS_ERR; } if (CheckTransPermission(mySessionName, pkgName, ACTION_OPEN) < SOFTBUS_OK) { LOG_ERR("TransOpenSession no permission!"); return SOFTBUS_PERMISSION_DENIED; } if (!TransSessionServerIsExist(mySessionName)) { LOG_ERR("session server invalid"); return INVALID_CHANNEL_ID; } return TransOpenChannel(mySessionName, peerSessionName, peerDeviceId, groupId, flags);}
该函数对入参进行校验之后,便调用TransOpenChannel进行处理,该函数源码如下:
int32_t TransOpenChannel(const char *mySessionName, const char *peerSessionName, const char *peerDeviceId, const char *groupId, int32_t flags){ int32_t channelId = INVALID_CHANNEL_ID; if (!IsValidString(mySessionName, SESSION_NAME_SIZE_MAX) || !IsValidString(peerSessionName, SESSION_NAME_SIZE_MAX) || !IsValidString(peerDeviceId, DEVICE_ID_SIZE_MAX) || !IsValidString(groupId, GROUP_ID_SIZE_MAX)) { return channelId; } ConnectOption connOpt = {0}; AppInfo *appInfo = GetAppInfo(mySessionName, peerSessionName, peerDeviceId, groupId, flags); if (appInfo == NULL) { LOG_ERR("get app info err"); return channelId; } int type = TransGetChannelType(); switch (type) { case CHANNEL_TYPE_PROXY: if (GetConnectOptionBr(peerDeviceId, &connOpt) != SOFTBUS_OK) { LOG_ERR("get connection opt err"); break; } if (TransProxyOpenProxyChannel(appInfo, &connOpt, &channelId) != SOFTBUS_OK) { LOG_ERR("open proxy channel err"); channelId = INVALID_CHANNEL_ID; } break;#ifndef SOFTBUS_WATCH case CHANNEL_TYPE_TCP_DIRECT: if (GetConnectOptionTcp(peerDeviceId, &connOpt) != SOFTBUS_OK) { LOG_ERR("get connection opt err"); break; } if (TransOpenTcpDirectChannel(appInfo, &connOpt, &channelId) != SOFTBUS_OK) { LOG_ERR("open direct channel err"); channelId = INVALID_CHANNEL_ID; } break;#endif default: break; } SoftBusFree(appInfo); return channelId;}
该函数分为2步:
- 调用GetAppInfo创建了一个新的appInfo
- 然后根据ChannelType的类型,选择对应的处理。
第2步以CHANNEL_TYPE_TCP_DIRECT为例,该场景下:
- 调用GetConnectOptionTcp获取对端的IP地址和Port号,并保存在connOpt中。
- 调用TransOpenTcpDirectChannel进行处理。
TransOpenTcpDirectChannel的源码如下:
int32_t TransOpenTcpDirectChannel(AppInfo *appInfo, const ConnectOption *connInfo, int *fd){ if (appInfo == NULL || connInfo == NULL || fd == NULL) { LOG_ERR("param is invalid."); return SOFTBUS_INVALID_PARAM; } char *ip = (char*)connInfo->info.ipOption.ip; int sessionPort = connInfo->info.ipOption.port; appInfo->routeType = WIFI_STA; SessionConn *newConn = (SessionConn*)SoftBusMalloc(sizeof(SessionConn)); if (newConn == NULL) { LOG_ERR("Malloc err."); return SOFTBUS_ERR; } if (memcpy_s(&newConn->appInfo, sizeof(AppInfo), appInfo, sizeof(AppInfo)) != EOK) { SoftBusFree(newConn); LOG_ERR("Memcpy ip err."); return SOFTBUS_ERR; } newConn->appInfo.fd = -1; newConn->serverSide = false; newConn->channelId = INVALID_CHANNEL_ID; if (strcpy_s(newConn->appInfo.peerData.ip, IP_LEN, ip) != EOK) { SoftBusFree(newConn); LOG_ERR("strcpy_s err."); return SOFTBUS_ERR; } newConn->appInfo.peerData.port = sessionPort; newConn->status = TCP_DIRECT_CHANNEL_STATUS_HANDSHAKING; newConn->timeout = 0; if (InitTdcInfo(newConn) != SOFTBUS_OK) { SoftBusFree(newConn); return SOFTBUS_ERR; } *fd = OpenConnTcp(appInfo, connInfo); if (*fd channelId); SoftBusFree(newConn); LOG_ERR("OpenConnTcp err."); return SOFTBUS_ERR; } newConn->appInfo.fd = *fd; newConn->channelId = *fd; if (AddTrigger(DIRECT_CHANNEL_SERVER, newConn->appInfo.fd, RW_TRIGGER) != SOFTBUS_OK) { TransCloseDirectChannel(newConn->channelId); SoftBusFree(newConn); LOG_ERR("AddTrigger failed"); return SOFTBUS_ERR; } return SOFTBUS_OK;}
该函数分为4步:
- 创建了一个SessionConn节点,并对其进行赋值操作。
- 调用InitTdcInfo对创建的SessionConn节点进行初始化。
- 调用OpenConnTcp,根据对端的IP和端口号建议Socket连接
- 调用AddTrigger将socket描述符添加到g_listenerList里面DIRECT_CHANNEL_SERVER模块对应的的info中。
这里整体代码比较简单,因此不展开。