搜索
bottom↓
回复: 28

freeswitch 折腾了一个星期 lua 实现的 act 程序,抛砖引玉

[复制链接]

出0入0汤圆

发表于 2017-7-25 10:38:36 | 显示全部楼层 |阅读模式
---上次发帖说用 sip做一个呼叫系统,折腾得好痛苦,如果有意的坛友可以参考一下,节省点时间和表情。肯定可以运行。如果有其中的高手,请指教一下。代码比较精糙。。哈

dbh=freeswitch.Dbh("odbc://fwsql");
laststat="";   --最后状态 1.hasline 2.notline 有否空内线 2.5 linenot  有空线到最后被用  3.linebusy  4.lineready 有空线是否能接入
badinline="";
function waittoinc(tmpsession)
  local waitTimes = 10;
  while tmpsession:ready() == false and waitTimes > 0 do  
     waitTimes = waitTimes - 1;  
  end
  return tmpsession:ready()
  
end

function playwavs(tmpsession,wavfiles)
  
  tmpsession:sleep(50);
    if tmpsession:ready() then
     freeswitch.consoleLog("err", "\n starting play wav");
     tmpsession:streamFile(wavfiles);
     freeswitch.consoleLog("err", "\n play wav end");
     end

  
end

function getoneinline(notline)   --获得一条空闲内线在 inlineinfo 表内
  local reinline="";
   
  dbh:query("select top 1 inline from inlineinfo where busy=0 and inline<>'"..notline.."' order by [index] asc,calltime asc"
,function(row) reinline=row.inline  end )
  if reinline==nil or reinline=="" then
    laststat="notline";
    return "";
  end
    laststat="hasline";
    badinline=reinline;
  return reinline;
end

function zoneinline(notline,calldh,callid) --获内线后,设置为忙
  
  local reinline;
  local revv;
  local ktnow=os.date("%Y-%m-%d %H:%M:%S", os.time());
  reinline=getoneinline(notline);
  if reinline==nil then
    reinline="";
    return reinline;
  end
  
  dbh:query("update inlineinfo set busy=1,outline='"..calldh.."',callid='"..callid.."',calltime='"..ktnow.."' where inline='"..reinline.."' and busy=0");
  revv=dbh:affected_rows();
  badinline=reinline;
  if revv>0 then
   return reinline;
  else
   laststat="linenot";
    return "";
  end
end

function callinline(notline,calldh,callid)
  local reinline=zoneinline(notline,calldh,callid);
  
   if reinline==nil or reinline=="" then
      return "",nil;
   end
  badinline=reinline;
  local tmpnum=reinline;
  local tmpsession= freeswitch.Session("user/"..tmpnum);
  
   if waittoinc(tmpsession) then
      laststat="lineready";
      return tmpnum,tmpsession;
    else

      dbh:query("update inlineinfo set busy=0,[index]=(select isnull(count(*),0) from inlineinfo where busy=0)+1 where inline='"..reinline.."'")  
     laststat="linebusy";
     return "",nil;
   end

end


local session1 = session;  

local cid=session1:getVariable("caller_id_number");
local dest_num=session1:getVariable("destination_number");
local kt=os.date("%Y-%m-%d %H:%M:%S", os.time());
local ktms=os.time();

dbh:query("insert into new通话(电话,kt,zt)values('"..cid.."','"..kt.."','"..dest_num.."')");

--playwavs(session1,"d:\\ffg\\wel.wav");
--如果座席所在的那条通道还没准备好,则进行等待
--session1:sleep(1800);
--if session1:ready() then
-- session1:answer();
-- end


local session2;
local inline;
local timess=0;
inline,session2=callinline("",dest_num,cid);--toonecall();

if inline=="" then
   
   session1:sleep(50);
    if (laststat=='linenot' or laststat=='linebusy') and badinline~='' and session1:ready() then
      freeswitch.consoleLog("err", "\n channels2 is not ready, try next. laststat:"..laststat);
      
      inline,session2=callinline(badinline,dest_num,cid);
    end
   
end

if inline=="" then
   session1:sleep(50);
   
    if (laststat=='linenot' or laststat=='linebusy') and badinline~='' and session1:ready() then
      freeswitch.consoleLog("err", "\n channels2 is not ready, try next. laststat:"..laststat);
      
      inline,session2=callinline(badinline,dest_num,cid);
    end
   
end

if  inline=="" then  
      
     -- 接通客户与座席
    -- session2:setVariable("destination_number",cid);
      
    freeswitch.consoleLog("err", "\n channels2 is not ready, please check it. laststat:"..laststat);
     timess=-1;
     playwavs(session1,"d:\\ffg\\busy.wav");
else  
    session1:sleep(50);
   
    if session1:ready() then
     
      freeswitch.bridge(session1, session2);
     
    else
      timess=-2;
    end
end  



local et=os.date("%Y-%m-%d %H:%M:%S", os.time())
local etms=os.time();

if timess==0 then
  timess=etms-ktms;
  
end
dbh:query("update inlineinfo set busy=0,[index]=(select isnull(count(*),0) from inlineinfo where busy=0)+1 where inline='"..inline.."'")
dbh:query("insert into 通话(电话,kt,zt,st)values('"..cid.."','"..kt.."','"..et.."',"..timess..")")
dbh:release()


----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最后说明,用的是 ms sql  上面是代码,下面表结构
USE [fwdb]
GO

/****** Object:  Table [dbo].[inlineinfo]    Script Date: 07/25/2017 10:32:40 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[inlineinfo](
        [id] [int] IDENTITY(1,1) NOT NULL,
        [inline] [varchar](40) NOT NULL,
        [outline] [varchar](40) NULL,
        [calltime] [varchar](20) NULL,
        [busy] [int] NOT NULL,
        [index] [int] NULL,
        [callid] [varchar](40) NOT NULL,
CONSTRAINT [PK_netinlineinfo] PRIMARY KEY CLUSTERED
(
        [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO


USE [fwdb]
GO

/****** Object:  Table [dbo].[通话]    Script Date: 07/25/2017 10:33:31 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[通话](
        [id] [int] IDENTITY(1,1) NOT NULL,
        [电话] [varchar](20) NULL,
        [kt] [varchar](20) NULL,
        [zt] [varchar](20) NULL,
        [st] [int] NULL,
CONSTRAINT [PK_通话] PRIMARY KEY CLUSTERED
(
        [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

USE [fwdb]
GO

/****** Object:  Table [dbo].[new通话]    Script Date: 07/25/2017 10:33:23 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[new通话](
        [id] [int] IDENTITY(1,1) NOT NULL,
        [电话] [varchar](20) NULL,
        [kt] [varchar](20) NULL,
        [zt] [varchar](20) NULL,
CONSTRAINT [PK_net通话] PRIMARY KEY CLUSTERED
(
        [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO









阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入8汤圆

发表于 2017-7-25 11:30:23 | 显示全部楼层
楼主,论坛有插入代码功能,建议以后发帖使用代码模式,阅读体验会好很多

  1. static void do_xxx(void)
  2. {

  3. }
复制代码

出0入0汤圆

 楼主| 发表于 2017-7-25 11:34:58 | 显示全部楼层
Jmhh247 发表于 2017-7-25 11:30
楼主,论坛有插入代码功能,建议以后发帖使用代码模式,阅读体验会好很多

...

哈,是的是的,代码量不多将就一下

出0入0汤圆

发表于 2017-7-26 15:47:51 | 显示全部楼层
代码比较精糙。。    =精辟+粗糙?哈哈

出0入0汤圆

发表于 2017-7-26 16:08:33 来自手机 | 显示全部楼层
sql语言,lua部分呢?

出0入0汤圆

 楼主| 发表于 2017-7-26 16:15:15 | 显示全部楼层
Excellence 发表于 2017-7-26 16:08
sql语言,lua部分呢?

上面 lua 下面 sql 表结构

出0入0汤圆

发表于 2017-7-26 17:28:34 | 显示全部楼层
daiqx 发表于 2017-7-26 16:15
上面 lua 下面 sql 表结构

谢谢分享。。。。

出215入118汤圆

发表于 2017-7-26 23:38:21 | 显示全部楼层
我最近也在玩这个,从移动要了个IMS固话号码,现在gateway和inbound都配置通了,可以打进来了,就是outbound不知道怎么配置,总打不出去,楼主可吧指导一下么?中国的拨号规则怎么写?Outbound应该怎么配置?

出0入0汤圆

 楼主| 发表于 2017-7-28 00:37:04 来自手机 | 显示全部楼层
拔号计划会设置么?会的话剩下的就是IMS的网关格式问题了。

出0入0汤圆

 楼主| 发表于 2017-7-28 01:25:28 来自手机 | 显示全部楼层
snowy 发表于 2017-7-26 23:38
我最近也在玩这个,从移动要了个IMS固话号码,现在gateway和inbound都配置通了,可以打进来了,就是outboun ...

就是使用网关的呼出字串格式,这个对的话就写到拔号计划,不过这个比较简单,所以有可能在getway上,有可能不对。还有你留意一下控制台的输出,应该有提示

出215入118汤圆

发表于 2017-7-28 09:44:20 | 显示全部楼层
daiqx 发表于 2017-7-28 01:25
就是使用网关的呼出字串格式,这个对的话就写到拔号计划,不过这个比较简单,所以有可能在getway上,有可 ...

谢谢 楼主,后来通过抓包分析,问题确实出在网关设置上,Caller ID In From 要设置为false,否则呼出时会使用本地号码和域名invite,IMS是不接受这样的不合法请求。

出0入0汤圆

 楼主| 发表于 2017-7-28 20:26:14 来自手机 | 显示全部楼层
snowy 发表于 2017-7-28 09:44
谢谢 楼主,后来通过抓包分析,问题确实出在网关设置上,Caller ID In From 要设置为false,否则呼出时会 ...

人生在于折腾,你可以将ims的网关\拔号计划发出来,有人也折腾这个时也可以参考一下。我比较喜欢使用脚本去代替拔号计划的逻辑。编程多于配置。

出0入0汤圆

 楼主| 发表于 2017-7-28 20:37:48 来自手机 | 显示全部楼层
snowy 发表于 2017-7-28 09:44
谢谢 楼主,后来通过抓包分析,问题确实出在网关设置上,Caller ID In From 要设置为false,否则呼出时会 ...

另外经过一段时间的折腾,fs灵活地用必须用脚本。比如lua。然后用脚本或更熟练地配置文件还是不够的,因为它们都是阻塞执行的不能异步。比如上面的代码其实还有一点问题,比如要整一个欢迎语,一边发送回铃音边桥接就不行了。最后就要折腾esl了。

出215入118汤圆

发表于 2017-7-28 21:22:06 | 显示全部楼层
本帖最后由 snowy 于 2017-7-28 21:24 编辑
daiqx 发表于 2017-7-28 20:26
人生在于折腾,你可以将ims的网关\拔号计划发出来,有人也折腾这个时也可以参考一下。我比较喜欢使用脚本 ...


响应号召,对接移动IMS的主要参数,请根据所在地移动提供的信息修改。拨号计划等玩转了,弄个比较完善的发上来。
  1. <include>
  2.   <gateway name="+86***********">
  3.   <!--/// account username *required* ///-->
  4.   <param name="username" value="+86***********"/>
  5.   <!--/// auth username *required* ///-->
  6.   <param name="auth-username" value="+86***********@ims.js.chinamobile.com"/>  
  7.   <!--/// auth realm: *optional* same as gateway name, if blank ///-->
  8.   <param name="realm" value="ims.js.chinamobile.com"/>
  9.   <!--/// username to use in from: *optional* same as  username, if blank ///-->
  10.   <!--<param name="from-user" value="cluecon"/>-->
  11.   <!--/// domain to use in from: *optional* same as  realm, if blank ///-->
  12.   <!--<param name="from-domain" value="asterlink.com"/>-->
  13.   <!--/// account password *required* ///-->
  14.   <param name="password" value="**********"/>
  15.   <!--/// extension for inbound calls: *optional* same as username, if blank ///-->
  16.   <!--<param name="extension" value="cluecon"/>-->
  17.   <!--/// proxy host: *optional* same as realm, if blank ///-->
  18.   <!--<param name="proxy" value="asterlink.com"/>-->
  19.   <!--/// send register to this proxy: *optional* same as proxy, if blank ///-->
  20.   <param name="register-proxy" value="sbc.chinamobile.com"/>
  21.   <!--/// send outbound data to this proxy: *optional* same as proxy, if blank ///-->
  22.   <param name="outbound-proxy" value="sbc.chinamobile.com"/>
  23.   <!--/// expire in seconds: *optional* 3600, if blank ///-->
  24.   <param name="expire-seconds" value="1800"/>
  25.   <!--/// do not register ///-->
  26.   <param name="register" value="true"/>
  27.   <!-- which transport to use for register -->
  28.   <param name="register-transport" value="udp"/>
  29.   <!--How many seconds before a retry when a failure or timeout occurs -->
  30.   <param name="retry-seconds" value="30"/>
  31.   <!--Use the callerid of an inbound call in the from field on outbound calls via this gateway -->
  32.   <param name="caller-id-in-from" value="false"/>
  33.   <!--extra sip params to send in the contact-->
  34.   <!--<param name="contact-params" value="tport=tcp"/>-->
  35.   <!--send an options ping every x seconds, failure will unregister and/or mark it down-->
  36.   <param name="ping" value="25"/>
  37.   <!--</gateway>-->
  38.   <!--rfc5626 : Abilitazione rfc5626 ///-->
  39.   <!--<param name="rfc-5626" value="true"/>-->
  40.   <!--rfc5626 : extra sip params to send in the contact-->
  41.   <!--<param name="reg-id" value="1"/>-->
  42. </include>
复制代码

出215入118汤圆

发表于 2017-7-28 21:27:56 | 显示全部楼层
本帖最后由 snowy 于 2017-7-28 21:30 编辑
daiqx 发表于 2017-7-28 20:37
另外经过一段时间的折腾,fs灵活地用必须用脚本。比如lua。然后用脚本或更熟练地配置文件还是不够的,因 ...


后来我发现了FusionPBX(底层是FreeSwitch,安装这个最好有爱国路由器带着,不然非常慢),这个有比较友好的图形化界面(很好看),而且全部功能都是免费开放的,不像FreePBX很多要付费的组件。您可以试试。

出0入0汤圆

 楼主| 发表于 2017-7-28 21:52:37 来自手机 | 显示全部楼层
snowy 发表于 2017-7-28 21:27
后来我发现了FusionPBX(底层是FreeSwitch,安装这个最好有爱国路由器带着,不然非常慢),这个有比较友 ...

谢谢分享,如果先知道fusionpbx的话,可能会减少很多时间,我先在ubunut安装fs,很多周折没有成功,就装win版的,安装非常容易,后来发现没有mod_lua模块,找编互联网也没有现成的,再下载源码,又发现只能vs2015才能编译,最后编译成功。linux版的有mod_lua  win版的没有,真气死。现在由纯手工配置入门也好应该会扎实很多,哈哈

出215入118汤圆

发表于 2017-7-29 13:47:34 | 显示全部楼层
daiqx 发表于 2017-7-28 21:52
谢谢分享,如果先知道fusionpbx的话,可能会减少很多时间,我先在ubunut安装fs,很多周折没有成功,就装w ...

一般来说LINUX下的开源软件在WIN下编译比LINUX下麻烦多了。

FusionPBX的出局路由:


Tag        Type        Data        Break        Inline        Group        Order         
condition        destination_number        ^(\+?\d{5,15})$                        0        5

长度在5位以上的,直接送到网关出局,4位以内保留给分机,软交换的好处是不像传统交换机那样要加拨数字。

^(\+?\d{5,15})$  这个REGEX基本搞定了01088888888  075588888888 +8688888888888 10000 10086之类的情况了,如果要拨110之类的,可以加拨区号来解决或者再加条3位数^(\d{3})$ 的优先路由。

出0入0汤圆

 楼主| 发表于 2017-7-29 16:27:47 来自手机 | 显示全部楼层
封装后拔号规则简洁了,不过本来原装的配置也不复杂

出0入0汤圆

 楼主| 发表于 2017-8-3 23:20:33 | 显示全部楼层
snowy 发表于 2017-7-29 13:47
一般来说LINUX下的开源软件在WIN下编译比LINUX下麻烦多了。

FusionPBX的出局路由:

你好!现在你的freeswitch进展如何了?现在我已经确认用ESL也搞不定自定义 Ringback 的问题。就是别人打入电话时交换机给他播放的回铃音,做成彩铃一样可自定义的。你有搞定这个需求吗?

出215入118汤圆

发表于 2017-8-4 08:36:31 | 显示全部楼层
本帖最后由 snowy 于 2017-8-4 08:50 编辑

你好,基本可以用了,外线的彩铃应该是运营商那边开吧?自己能做的应该只有内线拨内线的彩铃音。我现在拨打出去有些对方手机或电话的彩铃可以听到,有些听不到,不知道为什么,不过这个关系不大。

我遇到一个问题是DID被叫转移到外线,转不出去,看日志是超时。
例如:1. 分机1000拨打10086(其它外线号码都可以),接通后按转移键,输入另一分机号1001,可以呼出转移成功。
         2. 分机1000拨打10086(其它外线号码都可以),接通后按转移键,输入另一外线13888888,可以呼出转移成功。
         3.  分机1001呼叫分机1000,1000接通后按转移键,输入另一外线号1388888,可以呼入转移到外线成功。
         4. 外线拨打1000分机的DID号码,1000接通后按转移键,输入另一外线号,转移失败(FreePBX是可以成功的)。

您可以帮忙测试一下第4项的情况么?谢谢!
         

出0入0汤圆

 楼主| 发表于 2017-8-4 12:42:53 | 显示全部楼层
snowy 发表于 2017-8-4 08:36
你好,基本可以用了,外线的彩铃应该是运营商那边开吧?自己能做的应该只有内线拨内线的彩铃音。我现在拨打 ...

这种情况我都会用脚本实现的,先拨出外线成功后和现在的会话桥接,应该很好实现。用xml配置的不擅长。

出215入118汤圆

发表于 2017-8-4 19:58:44 | 显示全部楼层
daiqx 发表于 2017-8-4 12:42
这种情况我都会用脚本实现的,先拨出外线成功后和现在的会话桥接,应该很好实现。用xml配置的不擅长。 ...

FusionPBX不支持IAX2,我下载一份源码编译试试。

出0入0汤圆

 楼主| 发表于 2017-8-4 21:25:37 来自手机 | 显示全部楼层
snowy 发表于 2017-8-4 19:58
FusionPBX不支持IAX2,我下载一份源码编译试试。

如果fs可以支持,直接上配置文件就行,一定要Fusionpbx吗?有什么绝对的优势? 我用一个迂回的方法搞定播放自定义的早期媒体了。用execute_on_answer=lua 属性在桥接成功时调用 lua 发送一个自定义事件。 然后在主lua 接收到事件再playback 。 坑了两星期这个问题,因为资料太少纯靠google加折腾。在这过程中我更觉得如果不靠脚本或esl之类的调用,很难使用强大灵活的功能。走了很多弯路,lua->阻塞式,在桥接时居然不能播放语音,  然后就想上python的esl , 可惜在win下 esl的库死活编译不过,直接上c#的 socket 控制,发现资料更少。又回到lua,将就使用。 lua虽然 顺序阻塞式执行不能使用状态机等不足。但使用简单,功能足够强。在fs下强烈推荐。

出215入118汤圆

发表于 2017-8-22 11:42:10 | 显示全部楼层
我现在也开始折腾编译FREESWITCH了,主要是想集成进IAX2协议,并且试试自己 写LUA。楼主用的什么版本的LINUX和FREESWITCH的哪个分支?我尝试了一下,遇到不少问题,我用的V1.8和CENTOS7,目前遇到一个怎么也解决不了的问题(不编译这个模块就可以成功了):
making all mod_opus
make[4]: Entering directory `/root/freeswitch.git/src/mod/codecs/mod_opus'
Makefile:899: *** You must install libopus-dev to build mod_opus.  Stop.

libopus-dev 这个组件,我用yum install 安装后还是提示这个错误,下载opus的代码编译安装后也还是提示,请问您遇到过没?

出0入0汤圆

 楼主| 发表于 2017-8-22 12:46:23 | 显示全部楼层
snowy 发表于 2017-8-22 11:42
我现在也开始折腾编译FREESWITCH了,主要是想集成进IAX2协议,并且试试自己 写LUA。楼主用的什么版本的LINU ...

在实际应用需求的情况下,走的路线总是相似的。我用的是window版的1.68 ,只要是因为windows 版没有 mod_lua才去折腾源码编译。linux 下的安装我都没搞通呢,你这个出错,有可能libopus-dev版本不对,删除后找其它版本再试了。到最后不行换一个linux发行版。在linux的许多组件不同版本真的搞死人。

出215入118汤圆

发表于 2017-8-23 18:54:45 | 显示全部楼层
换成ubuntu一路坑,终于编译通过了,不过IAX2的支持还是不行,先玩玩LUA吧,您有没有相关脚本的集成入门指南?

出0入0汤圆

 楼主| 发表于 2017-8-23 20:45:05 | 显示全部楼层
snowy 发表于 2017-8-23 18:54
换成ubuntu一路坑,终于编译通过了,不过IAX2的支持还是不行,先玩玩LUA吧,您有没有相关脚本的集成入门指 ...

我当时在linux 下安装 fs 搞得焦燥,然后用lua也搞得超焦燥,基本是上面代码的几个指令,语法百度一下即可。
一般类似这样
http://blog.csdn.net/u010317005/article/details/51889022
还有 https://www.baidu.com/s?ie=utf-8 ... rsp=0&rsv_sug=2

还有 google   下  freeswitch lua   
一边搜索一边踩坑,反正 lua 可以热更新不用 reloadxml ,不断尝试

出100入101汤圆

发表于 2017-8-25 07:50:08 | 显示全部楼层
楼主用的哪个sip协议栈?

出0入0汤圆

 楼主| 发表于 2017-8-25 09:01:57 | 显示全部楼层
fengyunyu 发表于 2017-8-25 07:50
楼主用的哪个sip协议栈?

freeswitch 默认的
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 12:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表