+// -----------------------------------------------------------
+int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ if ( at->attr==ATTR_BITRATE_INPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+ ports[i*2+0]=ntohl(*(int*)(1+(char*)at->data));
+ } else if ( at->attr==ATTR_BITRATE_OUTPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+ ports[i*2+1]=ntohl(*(int*)(1+(char*)at->data));
+ }
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// -----------------------------------------------------------------
+int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
+
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ char *p;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+
+ for (i=0; i<nga->current->ports; ++i) {
+ if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
+ p=malloc(5);
+ *p=i+1;
+ *(int*)(p+1)=htonl(ports[2*i+0]);
+ pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
+ }
+ if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
+ p=malloc(5);
+ *p=i+1;
+ *(int*)(p+1)=htonl(ports[2*i+1]);
+ pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
+ }
+ }
+
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ goto end;
+ }
+
+
+ end:
+
+ return ret;
+
+}
+
+