当前位置:文档之家› freeswitch源码分析

freeswitch源码分析

freeswitch源码分析
freeswitch源码分析

总体来说,FreeSWITCH是一个基于组件的架构,如下图:

FreeSWITCH可以仅包括FS Core独立运行,外围各种不同种类的组件(module)增强了FreeSWITCH的功能。

开发者可以使用public API,遵循FreeSWITCH的接口标准,开发各种不同种类的module来增强FreeSWITCH的功能。

分析(一)

什么是FreeSWITCH

FreeSWITCH 是一个可扩展的开源跨平台的电话平台,支持音频、视频、文本或任何其他形式的媒体使用的协议的路由与交互。它于2006年成立。FreeSWITCH 也提供一个稳定的技术平台,可供许多电话应用开发利用的免费工具。

FreeSWITCH 最初由Anthony Minessale在Brian West和Michael Jerris的协助下设计和开发。这三人原先都是asterisk的开发者。这个项目的设计目标包括模块化、跨平台的支持,可扩展性和稳定性。今天,许多更多的开发者和使用者都为FreeSWITCH在贡献力量。

FreeSWITCH支持各种通信技术,如Skype,SIP、H.323、GoogleTalk,因此它容易与其他的开源PBX进行对接,如:sipXecs、Call Weaver、Bayonne、YATE 和Asterisk。

FreeSWITCH支持许多高级的SIP特性,如presence、BLF、SLA以及TCP TLS和sRTP。它也可以作为一个透明代理(有媒体或无媒体),扮演SBC和T.38代理的角色。

FreeSWITCH既支持宽带、窄带编码。Voice channel和conference bridge模块可以支持8k、16k、24k、32k和48k不同的码率,而且这些不同码率的通道可以进行bridge。如果G.729编解码经过授权,FreeSWITCH也是支持的。

FreeSWITCH支持Windows,Mac OS X ,Linux,BSD和Solaris的32与64位平台。

FreeSWITCH支持传真,无论是音频,还是T.38,而且可以微微音频和T.38的网关。

FreeSWITCH的很多开发者,都是非常有经验的开发人员。他们同时也参与其他开源软交换产品的开发,如:openSER, sipXecs, Asterisk和Call Weaver.

目录结构

├── configure

├── configure.in

├── Makefile.am

├── Makefile.in

├── modules.conf :需要编译的module列表

├── patches/ :补丁包

│ ├── MODAPP-293.diff

│ ├── mod_portaudio_snow_leopard.diff

│ ├── sofia.diff

│ └── zrtp_bnlib_pic.diff

├── src/

│ ├── CMakeLists.txt

│ ├── g711.c

│ ├── include/

│ ├── inet_pton.c

│ ├── Makefile.am

│ ├── Makefile.in

│ ├── mod/

│ ├── switch_apr.c

│ ├── switch_buffer.c

│ ├── switch.c :main入口

│ ├── switch_caller.c

│ ├── switch_channel.c

│ ├── switch_config.c

│ ├── switch_console.c

│ ├── switch_core_asr.c

│ ├── switch_core.c

│ ├── switch_core_codec.c

│ ├── switch_core_db.c

│ ├── switch_core_directory.c │ ├── switch_core_event_hook.c │ ├── switch_core_file.c

│ ├── switch_core_hash.c

│ ├── switch_core_io.c

│ ├── switch_core_media_bug.c

│ ├── switch_core_memory.c

│ ├── switch_core_port_allocator.c │ ├── switch_core_rwlock.c

│ ├── switch_core_session.c

│ ├── switch_core_speech.c

│ ├── switch_core_sqldb.c

│ ├── switch_core_state_machine.c │ ├── switch_core_timer.c

│ ├── switch_cpp.cpp

│ ├── switch_dso.c

│ ├── switch_event.c

│ ├── switch_ivr_async.c

│ ├── switch_ivr_bridge.c

│ ├── switch_ivr.c

│ ├── switch_ivr_menu.c

│ ├── switch_ivr_originate.c

│ ├── switch_ivr_play_say.c

│ ├── switch_ivr_say.c

│ ├── switch_loadable_module.c

│ ├── switch_log.c

│ ├── switch_mprintf.c

│ ├── switch_nat.c

│ ├── switch_odbc.c

│ ├── switch_pcm.c

│ ├── switch_profile.c

│ ├── switch_regex.c

│ ├── switch_resample.c

│ ├── switch_rtp.c

│ ├── switch_scheduler.c

│ ├── switch_stun.c

│ ├── switch_swig.c

│ ├── switch_swig.i

│ ├── switch_time.c

│ ├── switch_utils.c

│ ├── switch_xml.c

│ └── switch_xml_config.c

├── libs/

启动逻辑

FreeSwitch主程序的入库函数在src/switch.c文件中。Main函数启动:

1. 分析启动参数;

2. 为全局变量SWITCH_GLOBAL_dirs分配内存和赋值;

3. 创建pid文件;

4. 调用switch_core.c中的switch_core_init_and_modload()函数,初始化并加载所有的module,内部实现逻辑如下:

a) switch_core_init_and_modload

i. 首先调用switch_core_init

1. 初始化全局变量runtime的相关参数;

2. 对SWITCH_GLOBAL_dirs指定的目录进行创建;

3. load_mime_types加载conf/mime.types加载所有的mime类型;

4. 设置运行参数的默认值(注意:switch_find_local_ip获取本地IP的时候会访问外网);

5. 依次调用:switch_core_session_init、switch_console_init、

switch_event_init、switch_xml_init、switch_log_init进行相关的初始化,初始化的内容主要:hash、mutex。

6. 加载"switch.conf"配置文件;

7. switch_core_state_machine_init对state_machine进行初始化;

8. switch_core_sqldb_start,启动数据库相关线程;

9. switch_scheduler_task_thread_start,启动任务调度模块

10. switch_rtp_init:初始化rtp/zrtp相关的

11. switch_scheduler_add_task( heartbeat_callback),将心跳任务加入任务调度模块;

ii. switch_loadable_module_init()[switch_loadable_module.c]加载各module,freeswitch为了后续高效的运行module中的各种接口,将所有的接口都存放到了hash表中,每种接口建立了一个hash桶:

1. 初始化全局变量:loadable_modules的各类hash。

2. 加载集成module:CORE_SOFTTIMER_MODULE、CORE_PCM_MODULE;

a) switch_loadable_module_load_file进行module加载

i. 找到name##_module_interface的全局变量进行加载(module中宏

SWITCH_MODULE_DEFINITION定义的);

ii. 执行module->load(会初始化参数module_interface,是

SWITCH_MODULE_LOAD_FUNCTION定义的函数的一个参数),load中会增加各类接口:API、CHAT、APP、DIALPLAN、CODEC

b) switch_loadable_module_process

i. 遍历每个节点的endpoint_interface、codec_interface、

dialplan_interface、timer_interface、application_interface、

api_interface、file_interface、speech_interface、asr_interface、directory_interface、chat_interface、say_interface、management_interface,加载并存储到hash。

c) 创建线程,执行module->runtime()

3. 遍历conf/modules.conf加载所有配置的module;

4. 遍历conf/post_load_modules.conf加载所有配置的module;

5. 如果除集成module之外配置的模块为0,则从SWITCH_GLOBAL_dirs.mod_dir 加载所有的mod;

6. switch_loadable_module_runtime,为每个module的runtime入口创建一个线程并运行runtime;

分析(二)

事件处理模型

FreeSWITCH内部处理事件的基本数据结构和逻辑如下图:

1. freeSWITCH启动的时候,会创建3个EVENT_QUEUE,用来保存相关api、dialplan或呼叫触发的事件,队列长度为100000,每个队列的优先级不一样,平台根据事件的优先级将事件入队。注意:如果符合优先级要求的队列已经满了或其他原因造成入队失败,可能将事件放入到低优先级的队列[c1];

2. 每个EVENT_QUEUE会伴随一个event_thread线程,该线程的作用就是将EVENT_QUEUE的事件转移到EVENT_DISPATCH_QUEUE,队列长度为5000。FreeSWITCH启动的时候会创建1个EVENT_DISPATCH_QUEUE队列,正常情况下,event_thread会将事件放入到EVENT_DISPATCH_QUEUE[0],如果该队列已满或其他原因造成入队失败,再系统会动态创建EVENT_DISPATCH_QUEUE[1],[c2]将事件放入该队列,依次类推;

3. 每个EVENT_DISPATCH_QUEUE队列伴随一个event_dispatch_thread,该线程的作用就是将EVENT_DISPATCH_QUEUE的事件转移到对应的事件订约方队列NODE_EVENT_QUEUE,每个订阅会自带一个NODE_EVENT_QUEUE,长度为100000.。

媒体处理方式

FreeSWITCH有三种媒体处理方式,分别是:default、proxy、bypass,具体的应用和对比参考下表:

[c1]带来了可能的事件时序错误的问题

[c2]带来了可能的事件时序错误的问题

分析(三)

esl

api/bgapi调用逻辑

应用程序以普通方式对api的调用,是顺序、阻塞的,直到api执行完成才返回。

应用程序以bgapi的方式调用,是异步的,mod_event_sockt收到请求后,启动执行线程,直接返回。

如下所示,是api普通方式调用的时序图:

Application调用逻辑

应用程序调用dialplan相关的应用,都是异步模式,mod_event_socket收到请求之后,将请求放入到session的私有队列,接口直接返回。

获取事件

1. mod_event_socket启动的时候会订阅FreeSWITCH的所有事件,产生一个NODE_EVENT_QUEUE,mod_event_socket会根据不同的客户端订阅,给不同的客户端返回需要的事件;

2. 平台产生事件之后,会将事件放到mod_event_socket的NODE_EVENT_QUEUE 队列,mod_event_socket会遍历每个连接,将每个事件推送给订阅该事件的客户端;

3. 客户端调用esl接口获取事件,esl库首先根据check_q变量的设置,判断是否优先从自己的race_event队列(调用esl相关接口esl_send_recv执行程序的时候,为了获取相关api的返回值,esl需要从服务端等待消息,此过程中可能获取到了事件,则esl会将事件放入到race_event中)中获取,如果race_event没有,则首先从自己的缓存packet_buf中取数据处理,如果取到合适的数据直接返回,否则调用socket函数recv,按固定超时时间从

mod_event_socket上获取事件,将获取到的内容放入到packet_buf。

媒体应用处理

同步

典型application/api:playback、play_and_get_digist、read、record、park 以上这些应用,内部会循环调用switch_ivr_parse_all_events处理所有的dptool的请求,直到放音、录音、unpark等操作完成,因此不要在这些应用没有执行完的时候,继续执行其他应用。

如:在上次playback未完成的时候,又进行一次playback,这样会优先进行第二次playback,然后再进行第一次playback,形成了递归;playback和record 未完成操作直接调用,操作也类似,下图描述了一个递归的调用(在放音的过程中,调用record,如果record不被打断,则放音永远无法放出声音):

异步/订阅

典型application/api:uuid_record、record_session、start_dtmf。

以上这些应用,会给媒体流的read,增加hook(media_bug),不会阻塞媒体流。

典型场景

客户呼入

1) 客户呼入,mod_sofia会受到invite消息;

2) Mod_sofia获取一个session,启动session处理线程(session状态机);

3) Mod_sofia收到状态改变消息,设置session未INIT状态,后转为ROUTING 状态;

4) Session状态机,根据规则找到对应的dialplan定义,session状态变迁为EXECUTE;

5) 状态机根据dialplan的定义,执行对应的application。

平台外呼

1) 程序调用esl的接口发送外呼命令;

2) Mod_event_socket收到命令之后,调用mod_command的originate;

3) Originate调用switch_ivr定义的函数,创建session,启动session处理线程(状态机),同时状态变迁未INIT;

4) Mod_sofia发起invite请求,同时设置session状态为ROUTING;

5) 外部应答,session状态机变迁未CONSUME_MEDIA;

6) 程序通过esl接口,发送执行application命令,同时session的状态变迁未EXECUTE。

freeswitch 内核研究

2011-11-23 21:34:14| 分类:默认分类| 标签:|字号大中小订阅

比较零散,先放这留个脚印,慢慢添加整理。

1 .

freeswitch 分机号都保存在conf/directory 目录下

系统启动时加载分机信息到内存,当收到注册包时在directory目录下的usr 被搜寻,搜寻依据是注册请求的to ,from 头域的域名为系统所在的域名,

分机配置文件的分级结构:

domain

groups

group

usr

usr

group

groups

domain

directory 目录下包含若干xml文件,可以每个用户一个xml profile,系统启动时动态加载,

除了通过文件方式配置用户外,可以通过mod_xml_curl模块访问web server, web server 在

访问数据库,实现大批量分机的添加。

可以在用户的配置文件中设置一些附加给此用户的变量。

directory 目录的内容加载后可以被系统的所有模块获取,这样减少数据冗余。

dialplan 全局变量用$${default_areacode}" 访问,通道变量用${default_areacode}"访问

conf/var.xml文件定义了系统的全局变量。

单个用户的配置文件模板

//id 代表用户名,认证时用户名。

//此用户的

channel会设置此变量,用户的权限

其她可设置的变量:

accountcode :用户账户,会出现在CDR中。

user_context:用户打电话时走dialplan中context名为user_context 的值effective_caller_id_name:呼叫其他用户时显示给对方的用户名,(只有被叫在系统上注册才有效)

effective_caller_id_number :给对方显示的用户号,(只有被叫在系统上注册才有效)outbound_caller_id_name:通过sip中继外乎时给对方送的用户名

outbound_caller_id_number :通过sip中继外乎时给对方送的用户号码

callgroup :附加属性,

一个分机默认配置包含:

A username for SIP and for authorization

A voicemail password

A means of allowing/restricting dialling

A means of handling caller ID being sent out

Several arbitrary variables that can be used or ignored as needed

配置一个分机过程:

#>cd /usr/local/freeswitch/conf/directory/default

#>cp 1000.xml 1030.xml

Replace all occurrences of "1000" with "1030"

修改default dialplan

重新加载配置文件使配置生效:

reloadxml

控制台查看哪些分机主上已经注册:

sofia status profile internal

freeswitch的dialplan单独一个目录,分机的conext 为dialplan目录下的conext.xml 与外部链接:

freeswitch通过sip网关联系外部世界,freeswitch此时在sip server 来看是一个user.

配置网关方式:

创建中继文件:

conf/sip_profiles/external/test.xml

//sip provider提供的用户名及密码

-->

使配置生效:

cli 执行:

sofia profile external restart reloadxml (此命令会把正在通话的分机挂掉,更安全的

方式是用sofia profile external rescan reloadxml)

cli执行sofia status

返回系统sip 配置信息

主要分两类:1.网关(gateway) 2.本地注册用户(profile)

mod_xml_curl:

此模块为与Asterisk realtime 机制差不多,可以通过此模让freeswitch 需要时动态访问外部数据库或Web Server.这样可以实现动态控制freeswitch核心。

比如分机的添加可以通过在数据库配置,freeswitch通过此模块来加载分机。

通过此模块可以绑定:

1 .dialplan

每次呼叫,系统都会先访问8080

.....

2. 配置文件

sofia.conf 文件:

global_settings 节点:

子节点:

log-level

tracelevel

debug-presence

debug-sla

auto-restart

rewrite-multicasted-fs-path

to_host

original_server_host

original_hostname

profiles 节点:conf/sip_profiles/*.xml

默认有两个

internalx.ml

external.xml

freeswitch 高性能技术特性:memory pool,task queue, event driven,multithread,hash,state Machine,内存池,多线程,任务队列,事件驱动,哈希,状态机。

内核启动流程:

两个函数

switch_core_init 负责核心的初始化

apr_initialize(),

switch_core_session_init,

switch_core_hash_init,

switch_console_init,

switch_event_init,

switch_xml_init,

switch_log_init,

switch_core_state_machine_init

switch_scheduler_task_thread_start

switch_nat_late_init,

switch_rtp_init,

switch_loadable_module_init 各个模块的初始化。

呼叫流程:呼入

sip协议栈从传输层收到sip消息,最终转到SIPUA层,进入sofia_event_callback->sofia_queue_message

sofia_msg_thread_start->sofia_msg_thread_run->

sofia_process_dispatch_event-----------------

->our_sofia_event_callback->sofia_handle_sip_i_invite->switch_core_session _request

switch_core_session_thread_launch -> switch_core_session_thread_launch--->switch_ivr_originate()

外乎: fifo, conferrance,switch_ivr_originate

enterprise_originate_thread->

switch_ivr_originate----switch_core_session_outgoing_channel---->sofia_out going_channel->switch_core_session_request->

freeswitch 内核几个概念:session,channle, tec_private,event,

核心通过一个有限状态机来管理呼叫过程中每个状态对应的回调。

一个呼叫进入系统后建立一条channel,此channle属于一个server 维护的session,核心通过状态机来调度session以实现事件的流转。

一个典型的呼叫流程uac1-uas, uas-uac2, uac1-bridge-uac2,呼叫进入系统,系统建立session后启动switch_core_session_thread_launch 线程不断监听session状态,根据状态调用相应的回调,当然,这里的状态机是一个状态有限的,freeswitch 状态机分以下状态:

on_init,

on_routing,

on_execute,

on_hangup,

on_exchange_media

on_soft_execute,

on_consume_media,

on_hibernate,

on_reset,

on_park,

on_reporting,

on_destroy。

实际呼叫过程为这些状态的流转。

uac1-uas: 呼入系统,系统建立session:

sofia_handle_sip_i_invite->switch_core_session_request->switch_core_sessio

n_thread_launch,

解析请求后从CS_NEW -> CS_INIT,初始化后进入dialplan : CS_INIT ->

CS_ROUTING, 状态机回调switch_core_standard_on_routing 查找dialplan

系统根据主叫,被叫的sip设置查找其对应的dialplan,然后加载到内存,

呼叫状态转换:CS_ROUTING -> CS_EXECUT,状态机调用switch_core_standard_on_execute,然后按照规则一条一条执行刚加载的dialplan,

这里即是可编程软交换的体现,根据需求灵活控制提供给一个呼叫的服务。当执行到bridge action 时,是让系统呼叫uac2, 调用switch_ivr_originate 外乎uac2,创建uac2在服

务器端的session,channel,

最后启动状态机线程switch_core_session_thread_launch进入状态机模式,CS_NEW -> CS_INIT-> CS_ROUTING-> CS_CONSUME_MEDIA,

usc2最终应答200 ok,服务器根据200 ok sdp消息体与uac1提供的sdp协商,成

功后发200 ok给uac1,呼叫桥接成功。uac2状态机转换CS_CONSUME_MEDIA ->

CS_EXCHANGE_MEDIA,媒体流桥接开始。

状态机流转节点:

/*! \enum switch_channel_state_t \brief Channel States (these are the

defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA

are often overridden by specific apps)

 CS_NEW - Channel is newly created.

CS_INIT - Channel has been initilized. CS_ROUTING - Channel is looking for

an extension to execute. CS_SOFT_EXECUTE - Channel is ready to execute from 3rd party control. CS_EXECUTE - Channel is executing it's dialplan.

CS_EXCHANGE_MEDIA - Channel is exchanging media with another channel. CS_PARK - Channel is accepting media awaiting commands. CS_CONSUME_MEDIA - Channel

is consuming all media and dropping it. CS_HIBERNATE - Channel is in a sleep state.

CS_RESET - Channel is in a reset state. CS_HANGUP - Channel is flagged for hangup and ready to end. CS_REPORTING - Channel is ready to collect call detail.

CS_DESTROY - Channel is ready to be destroyed and out of the state machine

*/

Xmodem协议详解以及源代码剖析

研究 Xmodem 协议必看的 11个问题 Xmodem 协议作为串口数据传输主要的方式之一,恐怕只有做过 bootloader 的才有机会接触一下, 网上有关该协议的内容要么是英语要么讲解不详细。笔者以前写 bootloader 时研究过 1k-Xmodem ,参考了不少相关资料。这里和大家交流一下我对 Xmodem 的理解,多多指教! 1. Xmodem 协议是什么? XMODEM协议是一种串口通信中广泛用到的异步文件传输协议。分为标准Xmodem 和 1k-Xmodem 两种,前者以 128字节块的形式传输数据,后者字节块为 1k 即 1024字节,并且每个块都使用一个校验和过程来进行错误检测。在校验过程中如果接收方关于一个块的校验和与它在发送方的校验和相同时,接收方就向发送方发送一个确认字节 (ACK。由于 Xmodem 需要对每个块都进行认可, 这将导致性能有所下降, 特别是延时比较长的场合, 这种协议显得效率更低。 除了 Xmodem ,还有 Ymodem , Zmodem 协议。他们的协议内容和 Xmodem 类似,不同的是 Ymodem 允许批处理文件传输,效率更高; Zmodem 则是改进的了Xmodem ,它只需要对损坏的块进行重发,其它正确的块不需要发送确认字节。减少了通信量。 2. Xmodem 协议相关控制字符 SOH 0x01 STX 0x02 EOT 0x04 ACK 0x06 NAK 0x15

CAN 0x18 CTRLZ 0x1A 3.标准 Xmodem 协议(每个数据包含有 128字节数据帧格式 _______________________________________________________________ | SOH | 信息包序号 | 信息包序号的补码 | 数据区段 | 校验和 | |_____|____________|___________________|__________|____________| 4. 1k-Xmodem (每个数据包含有 1024字节数据帧格式 _______________________________________________________________ | STX | 信息包序号 | 信息包序号的补码 | 数据区段 | 校验和 | |_____|____________|___________________|__________|____________| 5.数据包说明 对于标准 Xmodem 协议来说,如果传送的文件不是 128的整数倍,那么最后一个数据包的有效内容肯定小于帧长,不足的部分需要用 CTRL- Z(0x1A来填充。这里可能有人会问,如果我传送的是 bootloader 工程生成的 .bin 文件, mcu 收到后遇到0x1A 字符会怎么处理?其实如果传送的是文本文件,那么接收方对于接收的内容是很容易识别的,因为 CTRL-Z 不是前 128个 ascii 码, 不是通用可见字符, 如果是二进制文件, mcu 其实也不会把它当作代码来执行。哪怕是 excel 文件等,由于其内部会有些结构表示各个字段长度等,所以不会读取多余的填充字符。否则 Xmodem太弱了。对于 1k-Xmodem ,同上理。 6.如何启动传输?

LWIP协议栈的分析和设计

---《计算机网络与控制》论文 LWIP协议栈的分析

摘要 近些年来,随着互联网和通讯技术的迅猛发展,除了计算机之外,大量的嵌入式设备也需求接入网络。目前,互联网中使用的通讯协议基本是TCP/IP协议族,可运行于不同的网络上,本文研究的就是嵌入式TCP/IP协议栈LWIP。文章首先分析了LWIP的整体结构和协议栈的实现,再介绍协议栈的内存管理,最后讲解协议栈应用程序接口。 关键词: 嵌入式系统;协议;LWIP;以太网 Abstract With the rapid development of internet and communication technology, Not only computers but also embeded equipments are need to connect networks. At present, the basic communication protocol using in internet is TCP/IP, it can run in different network. This paper analyses the Light-Weight TCP/IP. The process model of a protocol implementation and processing of every layer are described first, and then gives the detailed management of Buffer and memory. At last, a reference lwIP API is given. Key words: Embedded System, Protocol, Light weight TCP/IP,Ethernet 引言

lwip各层协议栈详解

竭诚为您提供优质文档/双击可除lwip各层协议栈详解 篇一:lwip协议栈源码分析 lwip源码分析 -----caoxw 1lwip的结构 lwip(lightweightinternetprotocol)的主要模块包括:配置模块、初始化模块、netif模块、mem(memp)模块、netarp模块、ip模块、udp模块、icmp模块、igmp模块、dhcp模块、tcp模块、snmp模块等。下面主要对我们需要关心的协议处理进行说明和梳理。配置模块: 配置模块通过各种宏定义的方式对系统、子模块进行了配置。比如,通过宏,配置了mem管理模块的参数。该配置模块还通过宏,配置了协议栈所支持的协议簇,通过宏定制的方式,决定了支持那些协议。主要的文件是opt.h。 初始化模块: 初始化模块入口的文件为tcpip.c,其初始化入口函数为: voidtcpip_init(void(*initfunc)(void*),void*arg)

该入口通过调用lwip_init()函数,初始化了所有的子模块,并启动了协议栈管理进程。同时,该函数还带有回调钩子及其参数。可以在需要的地方进行调用。 协议栈数据分发管理进程负责了输入报文的处理、超时处理、api函数以及回调的处理,原型如下: staticvoidtcpip_thread(void*arg) netif模块: netif模块为协议栈与底层驱动的接口模块,其将底层的一个网口设备描述成协议栈的一个接口设备(netinterface)。该模块的主要文件为netif.c。其通过链表的方式描述了系统中的所有网口设备。 netif的数据结构描述了网口的参数,包括ip地址、mac 地址、link状态、网口号、收发函数等等参数。一个网口设备的数据收发主要通过该结构进行。 mem(memp)模块: mem模块同一管理了协议栈使用的内容缓冲区,并管理pbuf结构以及报文的字段处理。主要的文件包括mem.c、memp.c、pbuf.c。 netarp模块: netarp模块是处理arp协议的模块,主要源文件为etharp.c。其主要入口函数为: err_tethernet_input(structpbuf*p,structnetif*netif)

LwIP协议栈源码详解

LwIP协议栈源码详解 ——TCP/IP协议的实现 Created by.. 老衲五木 at.. UESTC Contact me.. for_rest@https://www.doczj.com/doc/c5764173.html, 540535649@https://www.doczj.com/doc/c5764173.html,

前言 最近一个项目用到LwIP,恰好看到网上讨论的人比较多,所以有了写这篇学习笔记的冲动,一是为了打发点发呆的时间,二是为了吹过的那些NB。往往决定做一件事是简单的,而坚持做完这件事却是漫长曲折的,但终究还是写完了,时间开销大概为四个月,内存开销无法估计。。 这篇文章覆盖了LwIP协议大部分的内容,但是并不全面。它主要讲解了LwIP协议最重要也是最常被用到的部分,包括内存管理,底层网络接口管理,ARP层,IP层,TCP层,API 层等,这些部分是LwIP的典型应用中经常涉及到的。而LwIP协议的其他部分,包括UDP,DHCP,DNS,IGMP,SNMP,PPP等不具有使用共性的部分,这篇文档暂时未涉及。 原来文章是发在空间中的,每节每节依次更新,后来又改发为博客,再后来就干脆懒得发了。现在终于搞定,于是将所有文章汇总。绞尽脑汁的想写一段空前绝后,人见人爱的序言,但越写越觉得像是猫儿抓的一样。就这样,PS:由于本人文笔有限,情商又低,下里巴人一枚,所以文中的很多语句可能让您很纠结,您可以通过邮箱与我联系。共同探讨才是进步的关键。 最后,欢迎读者以任何方式使用与转载,但请保留作者相关信息,酱紫!码字。。。世界上最痛苦的事情莫过于此。。。 ——老衲五木

目录 1 移植综述------------------------------------------------------------------------------------------------------4 2 动态内存管理------------------------------------------------------------------------------------------------6 3 数据包pbuf--------------------------------------------------------------------------------------------------9 4 pbuf释放---------------------------------------------------------------------------------------------------13 5 网络接口结构-----------------------------------------------------------------------------------------------16 6 以太网数据接收--------------------------------------------------------------------------------------------20 7 ARP表-----------------------------------------------------------------------------------------------------23 8 ARP表查询-----------------------------------------------------------------------------------------------26 9 ARP层流程-----------------------------------------------------------------------------------------------28 10 IP层输入-------------------------------------------------------------------------------------------------31 11 IP分片重装1--------------------------------------------------------------------------------------------34 12 IP分片重装2--------------------------------------------------------------------------------------------37 13 ICMP处理-----------------------------------------------------------------------------------------------40 14 TCP建立与断开----------------------------------------------------------------------------------------43 15 TCP状态转换-------------------------------------------------------------------------------------------46 16 TCP控制块----------------------------------------------------------------------------------------------49 17 TCP建立流程-------------------------------------------------------------------------------------------53 18 TCP状态机----------------------------------------------------------------------------------------------56 19 TCP输入输出函数1-----------------------------------------------------------------------------------60 20 TCP输入输出函数2-----------------------------------------------------------------------------------63 21 TCP滑动窗口-------------------------------------------------------------------------------------------66 22 TCP超时与重传----------------------------------------------------------------------------------------69 23 TCP慢启动与拥塞避免-------------------------------------------------------------------------------73 24 TCP快速恢复重传和Nagle算法-------------------------------------------------------------------76 25 TCP坚持与保活定时器-------------------------------------------------------------------------------80 26 TCP定时器----------------------------------------------------------------------------------------------84 27 TCP终结与小结----------------------------------------------------------------------------------------88 28 API实现及相关数据结构-----------------------------------------------------------------------------91 29 API消息机制--------------------------------------------------------------------------------------------94 30 API函数及编程实例-----------------------------------------------------------------------------------97

lwip协议栈源码分析

LWIP源码分析 ----- caoxw 1 LWIP的结构 LWIP(Light weight internet protocol)的主要模块包括:配置模块、初始化模块、NetIf 模块、mem(memp)模块、netarp模块、ip模块、udp模块、icmp 模块、igmp模块、dhcp 模块、tcp模块、snmp模块等。下面主要对我们需要关心的协议处理进行说明和梳理。 配置模块: 配置模块通过各种宏定义的方式对系统、子模块进行了配置。比如,通过宏,配置了mem管理模块的参数。该配置模块还通过宏,配置了协议栈所支持的协议簇,通过宏定制的方式,决定了支持那些协议。主要的文件是opt.h。 初始化模块: 初始化模块入口的文件为tcpip.c,其初始化入口函数为: void tcpip_init(void (* initfunc)(void *), void *arg) 该入口通过调用lwip_init()函数,初始化了所有的子模块,并启动了协议栈管理进程。同时,该函数还带有回调钩子及其参数。可以在需要的地方进行调用。 协议栈数据分发管理进程负责了输入报文的处理、超时处理、API函数以及回调的处理,原型如下: static void tcpip_thread(void *arg) NetIf模块: Netif模块为协议栈与底层驱动的接口模块,其将底层的一个网口设备描述成协议栈的一个接口设备(net interface)。该模块的主要文件为netif.c。其通过链表的方式描述了系统中的所有网口设备。 Netif的数据结构描述了网口的参数,包括IP地址、MAC地址、link状态、网口号、收发函数等等参数。一个网口设备的数据收发主要通过该结构进行。 Mem(memp)模块: Mem模块同一管理了协议栈使用的内容缓冲区,并管理pbuf结构以及报文的字段处理。主要的文件包括mem.c、memp.c、pbuf.c。 netarp模块: netarp模块是处理arp协议的模块,主要源文件为etharp.c。其主要入口函数为: err_t ethernet_input(struct pbuf *p, struct netif *netif) 该入口函数通过判断输入报文p的协议类型来决定是按照arp协议进行处理还是将该报文提交到IP协议。如果报文是arp报文,该接口则调用etharp_arp_input,进行arp请求处理。 如果是ip报文,该接口就调用etharp_ip_input进行arp更新,并调用ip_input接口,将报文提交给ip层。 在该模块中,创建了设备的地址映射arp表,并提供地址映射关系查询接口。同时还提供了arp报文的发送接口。如下:

LwIP协议栈开发嵌入式网络的三种方法分析

LwIP协议栈开发嵌入式网络的三种方法分析 摘要轻量级的TCP/IP协议栈LwIP,提供了三种应用程序设计方法,且很容易被移植到多任务的操作系统中。本文结合μC/OS-II这一实时操作系统,以建立TCP服务器端通信为例,分析三种方法以及之间的关系,着重介绍基于raw API的应用程序设计。最后在ST公司STM32F107微处理器平台上验证,并给出了测试结果。 关键词LwIP协议栈;μC/OS-II;嵌入式网络;STM32F107; 随着嵌入式系统功能的多样化以及网络在各个领域的中的广泛应用,具备网络功能的嵌入式设备拥有更高的使用价值和更强的通用性。然而大部分嵌入式设备使用经济型处理器,受内存和速度限制,资源有限,不需要也不可能完整实现所有的TCP/IP协议,有时只需要满足实际需求就行。LwIP是由瑞典计算机科学研究院开发的轻量型TCP/IP协议栈,其特点是保持了以太网的基本功能,通过优化减少了对存储资源的占用。LwIP是免费、开源的,任何人可以使用,能够在裸机的环境下运行,当然设计的时候也考虑了将来的移植问题,可以很容易移植到多任务操作系统中。本文介绍了以ARM微处理器STM32F107和PHY接口DP83848为平台,构建的嵌入式系统中,采用LwIP和嵌入式操作系统μC/OS-II,使用协议栈提供的三种应用程序接口,实现嵌入式设备的网络通信功能。 1LwIP和μC/OS-II介绍 1.1 LwIP协议栈 LwIP协议是瑞士计算机科学院的Adam Dunkels等开发的一套用于嵌入式系统的开放源代码TCP/IP协议栈。LwIP含义是light weight(轻型)IP协议,在实现时保持了TCP协议的主要功能基础上减少对RAM的占用,一般它只需要几十K的RAM和40K左右的ROM 就可以运行,这使LwIP协议栈很适合在低端嵌入式系统中使用。 LwIP协议栈的设计才用分层结构的思想,每一个协议都作为一个模块来实现,提供一些与其它协议的接口函数。所有的TCP/IP协议栈都在一个进程当中,这样TCP/IP协议栈就和操作系统内核分开了。而应用程序既可以是单独的进程也可以驻留在TCP/IP进程中,它们之间利用ICP机制进行通讯。如果应用程序是单独的线程可以通过操作系统的邮箱、消息队列等,与协议栈进程通讯。如果应用程序驻留在协议栈进程中,则应用程序可以通过内部回调函数和协议栈进程通讯。 1.2 μC/OS-II实时操作系统 μC/OS-II是一个源码公开、可移植、可固化、可裁剪及占先式的实时多任务操作系统,是专门为嵌入式应用设计的实时操作系统内核,已广泛的应用在各种嵌入式系统中。 μC/OS-II是多任务系统,内核负责管理各个任务,每个任务都有其优先级,μC/OS-II 最多可以管理64个任务,其每个任务都拥有自己独立的堆栈。μC/OS-II提供了非常丰富的系统服务功能,比如信号量、消息邮箱、消息队列、事件标志、内存管理和时间管理等,这些功能可以帮助用户实现非常复杂的应用。 1.3 LwIP协议栈移植到μC/OS-II LwIP协议栈在设计的时候就考虑到了将来的移植问题,因此把所有与硬件、操作系统、编译器有关的部分都全部独立起来,形成了一个操作系统模拟层。操作系统模拟层用进程间的信号量、邮箱机制处理通信问题,而μC/OS-II是一个基于任务调度的嵌入式实时操作系

相关主题
文本预览
相关文档 最新文档